module Telephony
class Modem
attr_accessor :serialport, :sp, :sock
attr_accessor :baud, :data_bits, :parity, :stop_bits
attr_accessor :flowcontrol
attr_accessor :display
attr_reader :commandstate
NONE = SerialPort::NONE
HARD = SerialPort::HARD
SOFT = SerialPort::SOFT
SPACE = SerialPort::SPACE
MARK = SerialPort::MARK
EVEN = SerialPort::EVEN
ODD = SerialPort::ODD
def initialize(serialport = '/dev/ttyS0')
@serialport = serialport || '/dev/ttyS0'
@sp = nil
@baud = 2400
@data_bits = 8
@parity = NONE
@stop_bits = 1
@flowcontrol = NONE
@commandstate = true
@display = true
begin
@sp = SerialPort.create(serialport)
@sp.modem_params = {'baud' => @baud, 'data_bits' => @data_bits, 'parity' => @parity, 'stop_bits' => @stop_bits}
@sp.read_timeout = -1
@sp.rts = 1
@sp.dtr = 1 if sp.respond_to?:dtr=
@sock = @sp
@sock.extend(Rex::IO::Stream)
@sock.extend(Rex::IO::StreamAbstraction::Ext)
rescue ::Interrupt
raise $!
rescue ::Exception => e
print("Error opening serial port #{@serialport} : #{e.class} #{e} #{e.backtrace}\r\n")
return true
end
end
def method_missing(meth, *args); self.sp.send(meth, *args); end
def put_command(command, timeout)
switchback = false
if ! @commandstate
commandstate
switchback = true
end
begin
self.flush
@sp.puts command + "\r\n"
echo = get_response(timeout)
rescue ::Interrupt
raise $!
rescue ::Exception => e
print("Error sending command to modem: #{e.class} #{e} #{e.backtrace}\r\n")
return
end
result = get_response(timeout)
datastate if switchback == true
return result
end
def get_response(timeout)
time = Time.now
@sp.read_timeout = -1
result = ''
while Time.now <= time + timeout
begin
c = @sp.getc
if c
c = c.chr
result += c
if c == "\n"
result = result.chomp
break if result.length > 0
end
end
rescue ::Interrupt
raise $!
rescue ::Exception => e
print("Error reading from modem: #{e.class} #{e} #{e.backtrace}\r\n")
return
end
end
if result.length > 0
print "[m] #{result}\r\n" if @display
else
result = 'TIMEOUT'
end
return result
end
def commandstate
if ! @commandstate
@sp.break 10
@sp.puts '+++'
@sp.break 10
result = get_response(3)
if result != 'OK'
print( "Error switching to command state: FAILED\r\n" )
return false
else
@commandstate = true
end
end
return true
end
def datastate
if @commandstate
result = put_command('ATO0', 3)
if result =~ /CONNECT/i
@commandstate = false
else
print( "Error switching to data state: FAILED\r\n" )
return false
end
end
return true
end
def hangup
flush
if @commandstate == true
result = put_command('ATH0', 3)
return true if result == 'OK' or result == 'NO CARRIER'
else
if @sp.respond_to?:dtr=
@sp.dtr = 0
sleep 0.75
@sp.dtr = 1
result = get_response(3)
@commandstate = true if result == 'NO CARRIER'
return true
else
commandstate
result = put_command('ATH0', 3)
return true if result == 'OK'
end
end
return false
end
def flush
@sp.read_timeout = -1
while @sp.getc; end
end
def params=(params)
@sp.modem_params = params
end
end
end