Class: RubyAsterisk::AGI::Session
- Inherits:
-
Object
- Object
- RubyAsterisk::AGI::Session
- Defined in:
- lib/ruby-asterisk/agi/session.rb
Overview
Wraps a single FastAGI connection lifecycle.
Parses the AGI environment block sent by Asterisk at connection start, then provides command methods that write AGI commands and return parsed response hashes. Under an Async Fiber scheduler the socket reads/writes yield the Fiber rather than blocking a thread.
Instance Attribute Summary collapse
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#socket ⇒ Object
readonly
Returns the value of attribute socket.
Instance Method Summary collapse
-
#answer ⇒ Object
-- Existing wrappers (rewritten to use Protocol.format_command) -------.
- #channel_status(channel = nil) ⇒ Object
- #database_del(family, key) ⇒ Object
- #database_deltree(family, keytree = nil) ⇒ Object
-
#database_get(family, key) ⇒ Object
-- AstDB commands -----------------------------------------------------.
- #database_put(family, key, value) ⇒ Object
-
#dial(target, timeout: 30, options: '') ⇒ Object
Originate a call leg via Dial dialplan application.
- #exec(application, *args) ⇒ Object
-
#execute(command_string) ⇒ Hash
Send a raw AGI command string and return the parsed response Hash.
- #get_data(filename, timeout: 5000, max_digits: 1024) ⇒ Object
- #get_variable(name) ⇒ Object
- #hangup(channel = nil) ⇒ Object
-
#initialize(socket, logger: Logger.new($stdout), env_timeout: 10) ⇒ Session
constructor
A new instance of Session.
-
#read_env ⇒ Object
Read the initial AGI environment block (agi_key: value lines until blank line).
-
#record_file(filename, format: 'wav', escape_digits: '#', timeout_ms: -1,, offset: 0, beep: true, silence: nil) ⇒ Object
Record audio to a file.
- #say_digits(digits, escape_digits = '') ⇒ Object
- #say_number(number, escape_digits = '') ⇒ Object
- #send_image(filename) ⇒ Object
- #send_text(text) ⇒ Object
- #set_variable(name, value) ⇒ Object
- #stream_file(filename, escape_digits = '') ⇒ Object
- #verbose(message, level: 1) ⇒ Object
-
#wait_for_digit(timeout_ms = 5000) ⇒ Object
Block until a DTMF digit is pressed or timeout expires.
Constructor Details
#initialize(socket, logger: Logger.new($stdout), env_timeout: 10) ⇒ Session
Returns a new instance of Session.
23 24 25 26 27 28 |
# File 'lib/ruby-asterisk/agi/session.rb', line 23 def initialize(socket, logger: Logger.new($stdout), env_timeout: 10) @socket = socket @logger = logger @env = {} @env_timeout = env_timeout end |
Instance Attribute Details
#env ⇒ Object (readonly)
Returns the value of attribute env.
16 17 18 |
# File 'lib/ruby-asterisk/agi/session.rb', line 16 def env @env end |
#socket ⇒ Object (readonly)
Returns the value of attribute socket.
16 17 18 |
# File 'lib/ruby-asterisk/agi/session.rb', line 16 def socket @socket end |
Instance Method Details
#answer ⇒ Object
-- Existing wrappers (rewritten to use Protocol.format_command) -------
73 74 75 |
# File 'lib/ruby-asterisk/agi/session.rb', line 73 def answer execute('ANSWER') end |
#channel_status(channel = nil) ⇒ Object
147 148 149 |
# File 'lib/ruby-asterisk/agi/session.rb', line 147 def channel_status(channel = nil) channel ? execute("CHANNEL STATUS #{channel}") : execute('CHANNEL STATUS') end |
#database_del(family, key) ⇒ Object
161 162 163 |
# File 'lib/ruby-asterisk/agi/session.rb', line 161 def database_del(family, key) execute("DATABASE DEL #{family} #{key}") end |
#database_deltree(family, keytree = nil) ⇒ Object
165 166 167 |
# File 'lib/ruby-asterisk/agi/session.rb', line 165 def database_deltree(family, keytree = nil) keytree ? execute("DATABASE DELTREE #{family} #{keytree}") : execute("DATABASE DELTREE #{family}") end |
#database_get(family, key) ⇒ Object
-- AstDB commands -----------------------------------------------------
153 154 155 |
# File 'lib/ruby-asterisk/agi/session.rb', line 153 def database_get(family, key) execute("DATABASE GET #{family} #{key}") end |
#database_put(family, key, value) ⇒ Object
157 158 159 |
# File 'lib/ruby-asterisk/agi/session.rb', line 157 def database_put(family, key, value) execute("DATABASE PUT #{family} #{key} #{Protocol.quote(value)}") end |
#dial(target, timeout: 30, options: '') ⇒ Object
Originate a call leg via Dial dialplan application.
116 117 118 119 120 |
# File 'lib/ruby-asterisk/agi/session.rb', line 116 def dial(target, timeout: 30, options: '') args = [target, timeout.to_s] args << unless .to_s.empty? execute("EXEC Dial #{Protocol.quote(args.join(','))}") end |
#exec(application, *args) ⇒ Object
93 94 95 |
# File 'lib/ruby-asterisk/agi/session.rb', line 93 def exec(application, *args) execute("EXEC #{application} #{Protocol.quote(args.join(','))}") end |
#execute(command_string) ⇒ Hash
Send a raw AGI command string and return the parsed response Hash.
Handles Asterisk's two-line 520- syntax-error format by accumulating
continuation lines until the closing 520 End of proper usage. line.
Any embedded CR/LF in command_string is stripped before sending: AGI is
a line-oriented protocol, so a newline in a (possibly caller-controlled)
argument or identifier would otherwise inject additional commands.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/ruby-asterisk/agi/session.rb', line 54 def execute(command_string) line = command_string.to_s.delete("\r\n") @socket.write("#{line}\n") line = @socket.gets raise Error, 'Connection closed by Asterisk' unless line raise HangupError, 'Channel hung up' if line.chomp == 'HANGUP' response = Protocol.parse_response(line) if response[:code] >= 500 response = Protocol.collect_multiline_error(line.chomp, response, @socket) raise Error, "AGI error (#{response[:code]}): #{response[:data]}" end response end |
#get_data(filename, timeout: 5000, max_digits: 1024) ⇒ Object
105 106 107 |
# File 'lib/ruby-asterisk/agi/session.rb', line 105 def get_data(filename, timeout: 5000, max_digits: 1024) execute("GET DATA #{Protocol.quote(filename)} #{timeout} #{max_digits}") end |
#get_variable(name) ⇒ Object
101 102 103 |
# File 'lib/ruby-asterisk/agi/session.rb', line 101 def get_variable(name) execute("GET VARIABLE #{name}") end |
#hangup(channel = nil) ⇒ Object
77 78 79 |
# File 'lib/ruby-asterisk/agi/session.rb', line 77 def hangup(channel = nil) channel ? execute("HANGUP #{channel}") : execute('HANGUP') end |
#read_env ⇒ Object
Read the initial AGI environment block (agi_key: value lines until blank line).
33 34 35 36 37 38 39 |
# File 'lib/ruby-asterisk/agi/session.rb', line 33 def read_env with_env_timeout do @env = Protocol.parse_env_block(@socket) do |line| @logger.debug("AGI env: unexpected line: #{line}") end end end |
#record_file(filename, format: 'wav', escape_digits: '#', timeout_ms: -1,, offset: 0, beep: true, silence: nil) ⇒ Object
Record audio to a file.
131 132 133 134 135 136 137 |
# File 'lib/ruby-asterisk/agi/session.rb', line 131 def record_file(filename, format: 'wav', escape_digits: '#', timeout_ms: -1, offset: 0, beep: true, silence: nil) cmd = "RECORD FILE #{Protocol.quote(filename)} #{format} " \ "#{Protocol.quote(escape_digits)} #{timeout_ms} #{offset}" cmd += ' BEEP' if beep cmd += " s=#{silence}" if silence execute(cmd) end |
#say_digits(digits, escape_digits = '') ⇒ Object
85 86 87 |
# File 'lib/ruby-asterisk/agi/session.rb', line 85 def say_digits(digits, escape_digits = '') execute("SAY DIGITS #{digits} #{Protocol.escape_argument(escape_digits)}") end |
#say_number(number, escape_digits = '') ⇒ Object
89 90 91 |
# File 'lib/ruby-asterisk/agi/session.rb', line 89 def say_number(number, escape_digits = '') execute("SAY NUMBER #{number} #{Protocol.escape_argument(escape_digits)}") end |
#send_image(filename) ⇒ Object
143 144 145 |
# File 'lib/ruby-asterisk/agi/session.rb', line 143 def send_image(filename) execute("SEND IMAGE #{filename}") end |
#send_text(text) ⇒ Object
139 140 141 |
# File 'lib/ruby-asterisk/agi/session.rb', line 139 def send_text(text) execute("SEND TEXT #{Protocol.quote(text)}") end |
#set_variable(name, value) ⇒ Object
97 98 99 |
# File 'lib/ruby-asterisk/agi/session.rb', line 97 def set_variable(name, value) execute("SET VARIABLE #{name} #{Protocol.quote(value)}") end |
#stream_file(filename, escape_digits = '') ⇒ Object
81 82 83 |
# File 'lib/ruby-asterisk/agi/session.rb', line 81 def stream_file(filename, escape_digits = '') execute("STREAM FILE #{Protocol.quote(filename)} #{Protocol.quote(escape_digits)}") end |
#verbose(message, level: 1) ⇒ Object
109 110 111 |
# File 'lib/ruby-asterisk/agi/session.rb', line 109 def verbose(, level: 1) execute("VERBOSE #{Protocol.quote()} #{level}") end |
#wait_for_digit(timeout_ms = 5000) ⇒ Object
Block until a DTMF digit is pressed or timeout expires. Like every verb this returns the parsed response Hash { code:, result:, data: }; the pressed key's decimal ASCII value (or -1 on timeout) is in response.
126 127 128 |
# File 'lib/ruby-asterisk/agi/session.rb', line 126 def wait_for_digit(timeout_ms = 5000) execute("WAIT FOR DIGIT #{timeout_ms}") end |