class Net::Telnet::RFC2217
Constants
- COM_PORT_OPTION
- EVEN
- FLOWCONTROL_SUSPEND
- FLOWCONTROL_SUSPEND_RESPONSE
- MARK
- NONE
- NOTIFY_LINESTATE
- NOTIFY_LINESTATE_RESPONSE
- NOTIFY_MODEMSTATE
- NOTIFY_MODEMSTATE_RESPONSE
- ODD
- PURGE_DATA
- PURGE_DATA_RESPONSE
- SET_BAUDRATE
- SET_BAUDRATE_RESPONSE
- SET_CONTROL
- SET_CONTROL_RESPONSE
- SET_DATASIZE
- SET_DATASIZE_RESPONSE
- SET_LINESTATE_MASK
- SET_LINESTATE_MASK_RESPONSE
- SET_MODEMSTATE_MASK
- SET_MODEMSTATE_MASK_RESPONSE
- SET_PARITY
- SET_PARITY_RESPONSE
- SET_STOPSIZE
- SET_STOPSIZE_RESPONSE
- SPACE
- VERSION
Attributes
baud[R]
data_bits[R]
parity[R]
stop_bits[R]
telnet[R]
Public Class Methods
new(host, port: 23, baud: 115200, data_bits: 8, parity: :none, stop_bits: 1, &block)
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 34 def initialize(host, port: 23, baud: 115200, data_bits: 8, parity: :none, stop_bits: 1, &block) set_modem_params(baud: baud, data_bits: data_bits, parity: parity, stop_bits: stop_bits) options = { 'Host' => host, 'Port' => port, } options['Binmode'] = true options['Telnetmode'] = false @telnet = Telnet.new(options, &block) telnet.write(IAC + WILL + COM_PORT_OPTION) sock.flush @buffer = '' start = Time.now.to_f loop do raise "could not negotiate serial port in time" if Time.now.to_f - start > 5 break if @negotiated readpartial(0) end end
open(**kwargs) { |sp| ... }
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 17 def open(**kwargs) sp = new(opt**kwargs) if block_given? begin yield sp ensure sp.close end nil else nil end end
Public Instance Methods
close()
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 174 def close telnet.close end
flush()
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 170 def flush sock.flush end
read(length, outbuf = '')
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 70 def read(length, outbuf = '') readpartial(length, outbuf) while outbuf.length < length outbuf.concat(readpartial(length - outbuf.length)) end outbuf end
read_nonblock(length, outbuf = '', options = {})
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 122 def read_nonblock(length, outbuf = '', options = {}) if outbuf == ({ exception: false }) options = outbuf outbuf = '' end loop do result = wait_readable(0) if result == nil raise WaitReadable unless options[:exception] == false return :wait_readable end # we have to try to consume control characters first readpartial(0) # and then only do a real read if we have something return readpartial(length, outbuf) unless @buffer.empty? # otherwise loop and see if there's more there end end
readbyte()
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 78 def readbyte read(1)&.[](0) end
Also aliased as: getbyte
readpartial(length, outbuf = '')
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 83 def readpartial(length, outbuf = '') loop do # 0 is special and means "just see if there's data to read" break if length != 0 && @buffer.length != 0 raise "could not negotiate serial port in first 1MB of data" if @buffer.length >= 1024 * 1024 data = sock.sysread([length - @buffer.length, 64 * 1024].max) # avoid getting caught in the middle of a control sequence while (data[-1] == IAC && sock.wait_readable(0)) data.concat(sock.sysread(16)) end data = @telnet.preprocess(data) do |control| if DO[0] == control[0] && COM_PORT_OPTION == control[1] # start negotiation write_modem_params @negotiated = true true elsif DONT[0] == control[0] && COM_PORT_OPTION == control[1] raise "Serial port control not supported" elsif (WILL[0] == control[0] || DONT[0] == control[0]) && OPT_ECHO == control[1] # just ignore echo requests true else false end end @buffer.concat(data) break if length == 0 end length = [length, @buffer.length].min outbuf.replace(@buffer[0...length]) @buffer = @buffer[length..-1] outbuf end
ready?()
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 148 def ready? loop do return true unless @buffer.empty? return false if sock.wait_readable(0).nil? # consume control characters first readpartial(0) end end
set_modem_params(baud: nil, data_bits: nil, parity: nil, stop_bits: nil)
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 55 def set_modem_params(baud: nil, data_bits: nil, parity: nil, stop_bits: nil) raise ArgumentError, "Parity must be :none, :even, :odd, :mark, or :space" unless parity.nil? || %i{none even odd mark space}.include?(parity) @baud ||= baud || 115200 @data_bits ||= data_bits || 8 @parity ||= parity || :none @stop_bits ||= stop_bits || 1 write_modem_params if telnet end
sock()
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 66 def sock @telnet.sock end
ungetbyte(b)
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 157 def ungetbyte(b) @buffer.insert(0, b.chr) end
ungetc(c)
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 161 def ungetc(c) @buffer.insert(0, c) end
wait_readable(timeout = nil)
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 141 def wait_readable(timeout = nil) return true unless @buffer.empty? result = sock.wait_readable(timeout) result = self if result == sock result end
write(string)
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 165 def write(string) string = string.gsub(/#{IAC}/no, IAC + IAC) telnet.write(string) end
Private Instance Methods
write_modem_params()
click to toggle source
# File lib/net/telnet/rfc2217.rb, line 214 def write_modem_params telnet.write( IAC + SB + COM_PORT_OPTION + SET_BAUDRATE + [baud].pack("N") + IAC + SE + IAC + SB + COM_PORT_OPTION + SET_DATASIZE + data_bits.chr + IAC + SE + IAC + SB + COM_PORT_OPTION + SET_STOPSIZE + stop_bits.chr + IAC + SE + IAC + SB + COM_PORT_OPTION + SET_PARITY + const_get(parity.upcase, false).chr + IAC + SE) sock.flush end