Class: Net::Telnet::RFC2217
- Inherits:
-
Object
- Object
- Net::Telnet::RFC2217
- Defined in:
- lib/net/telnet/rfc2217/telnet.rb,
lib/net/telnet/rfc2217/version.rb,
lib/net/telnet/rfc2217.rb
Defined Under Namespace
Modules: TelnetExtensions Classes: WaitReadable
Constant Summary collapse
- VERSION =
'1.0.0'
Instance Attribute Summary collapse
-
#baud ⇒ Object
readonly
Returns the value of attribute baud.
-
#data_bits ⇒ Object
readonly
Returns the value of attribute data_bits.
-
#parity ⇒ Object
readonly
Returns the value of attribute parity.
-
#stop_bits ⇒ Object
readonly
Returns the value of attribute stop_bits.
-
#telnet ⇒ Object
readonly
Returns the value of attribute telnet.
Class Method Summary collapse
Instance Method Summary collapse
- #close ⇒ Object
- #flush ⇒ Object
-
#initialize(host, port: 23, baud: 115200, data_bits: 8, parity: :none, stop_bits: 1, &block) ⇒ RFC2217
constructor
A new instance of RFC2217.
- #read(length, outbuf = '') ⇒ Object
- #read_nonblock(length, outbuf = '', options = {}) ⇒ Object
- #readbyte ⇒ Object (also: #getbyte)
- #readpartial(length, outbuf = '') ⇒ Object
- #ready? ⇒ Boolean
- #set_modem_params(baud: nil, data_bits: nil, parity: nil, stop_bits: nil) ⇒ Object
- #sock ⇒ Object
- #ungetbyte(b) ⇒ Object
- #ungetc(c) ⇒ Object
- #wait_readable(timeout = nil) ⇒ Object
- #write(string) ⇒ Object
Constructor Details
#initialize(host, port: 23, baud: 115200, data_bits: 8, parity: :none, stop_bits: 1, &block) ⇒ RFC2217
Returns a new instance of RFC2217.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/net/telnet/rfc2217.rb', line 35 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) = { 'Host' => host, 'Port' => port, } ['Binmode'] = true ['Telnetmode'] = false @telnet = Telnet.new(, &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 |
Instance Attribute Details
#baud ⇒ Object (readonly)
Returns the value of attribute baud.
33 34 35 |
# File 'lib/net/telnet/rfc2217.rb', line 33 def baud @baud end |
#data_bits ⇒ Object (readonly)
Returns the value of attribute data_bits.
33 34 35 |
# File 'lib/net/telnet/rfc2217.rb', line 33 def data_bits @data_bits end |
#parity ⇒ Object (readonly)
Returns the value of attribute parity.
33 34 35 |
# File 'lib/net/telnet/rfc2217.rb', line 33 def parity @parity end |
#stop_bits ⇒ Object (readonly)
Returns the value of attribute stop_bits.
33 34 35 |
# File 'lib/net/telnet/rfc2217.rb', line 33 def stop_bits @stop_bits end |
#telnet ⇒ Object (readonly)
Returns the value of attribute telnet.
15 16 17 |
# File 'lib/net/telnet/rfc2217.rb', line 15 def telnet @telnet end |
Class Method Details
.open(**kwargs) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/net/telnet/rfc2217.rb', line 18 def open(**kwargs) sp = new(opt**kwargs) if block_given? begin yield sp ensure sp.close end nil else nil end end |
Instance Method Details
#close ⇒ Object
175 176 177 |
# File 'lib/net/telnet/rfc2217.rb', line 175 def close telnet.close end |
#flush ⇒ Object
171 172 173 |
# File 'lib/net/telnet/rfc2217.rb', line 171 def flush sock.flush end |
#read(length, outbuf = '') ⇒ Object
71 72 73 74 75 76 77 |
# File 'lib/net/telnet/rfc2217.rb', line 71 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 = {}) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/net/telnet/rfc2217.rb', line 123 def read_nonblock(length, outbuf = '', = {}) if outbuf == ({ exception: false }) = outbuf outbuf = '' end loop do result = wait_readable(0) if result == nil raise WaitReadable unless [: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 ⇒ Object Also known as: getbyte
79 80 81 |
# File 'lib/net/telnet/rfc2217.rb', line 79 def readbyte read(1)&.[](0) end |
#readpartial(length, outbuf = '') ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/net/telnet/rfc2217.rb', line 84 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? ⇒ Boolean
149 150 151 152 153 154 155 156 |
# File 'lib/net/telnet/rfc2217.rb', line 149 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) ⇒ Object
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/net/telnet/rfc2217.rb', line 56 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 ⇒ Object
67 68 69 |
# File 'lib/net/telnet/rfc2217.rb', line 67 def sock @telnet.sock end |
#ungetbyte(b) ⇒ Object
158 159 160 |
# File 'lib/net/telnet/rfc2217.rb', line 158 def ungetbyte(b) @buffer.insert(0, b.chr) end |
#ungetc(c) ⇒ Object
162 163 164 |
# File 'lib/net/telnet/rfc2217.rb', line 162 def ungetc(c) @buffer.insert(0, c) end |
#wait_readable(timeout = nil) ⇒ Object
142 143 144 145 146 147 |
# File 'lib/net/telnet/rfc2217.rb', line 142 def wait_readable(timeout = nil) return true unless @buffer.empty? result = sock.wait_readable(timeout) result = self if result == sock result end |
#write(string) ⇒ Object
166 167 168 169 |
# File 'lib/net/telnet/rfc2217.rb', line 166 def write(string) string = string.gsub(/#{IAC}/no, IAC + IAC) telnet.write(string) end |