net-telnet-rfc2217 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 80efcdecc1ad8f12d8546c6487de4ced9f2042beb7126046fd616cb4f507685c
4
+ data.tar.gz: 88afffcd92a3d0764047da96e01f1be3811614247230d4d58e563963d894ad06
5
+ SHA512:
6
+ metadata.gz: 984cfeac7c438e93816979be2ea410d398376e7d1bd0255c85e10e94bd18791c346a30357a3e36d650278ade772aff53b147e5f29485079d320995b3d606ec1d
7
+ data.tar.gz: 23c8a0d1ee8b9ac9179973f9ec8defde1402b21022febe9b26c29370eaff7def8f509c5c9848ec2cabc09c5013931eefb5224481a0eb9615f81eb9dcb96dee15
@@ -0,0 +1 @@
1
+ require 'net/telnet/rfc2217'
@@ -0,0 +1,181 @@
1
+ require 'net/telnet'
2
+ require 'byebug'
3
+
4
+ # have to patch Telnet to allow us to read control sequences
5
+ require 'net/telnet/rfc2217/telnet'
6
+ Net::Telnet.prepend(Net::Telnet::RFC2217::TelnetExtensions)
7
+
8
+ module Net
9
+ class Telnet
10
+ class RFC2217
11
+ attr_reader :telnet
12
+
13
+ COM_PORT_OPTION = 44.chr
14
+
15
+ SET_BAUDRATE = 1.chr
16
+ SET_DATASIZE = 2.chr
17
+ SET_PARITY = 3.chr
18
+ SET_STOPSIZE = 4.chr
19
+ SET_CONTROL = 5.chr
20
+ NOTIFY_LINESTATE = 6.chr
21
+ NOTIFY_MODEMSTATE = 7.chr
22
+ FLOWCONTROL_SUSPEND = 8.chr
23
+ SET_LINESTATE_MASK = 10.chr
24
+ SET_MODEMSTATE_MASK = 11.chr
25
+ PURGE_DATA = 12.chr
26
+
27
+ SET_BAUDRATE_RESPONSE = 101.chr
28
+ SET_DATASIZE_RESPONSE = 102.chr
29
+ SET_PARITY_RESPONSE = 103.chr
30
+ SET_STOPSIZE_RESPONSE = 104.chr
31
+ SET_CONTROL_RESPONSE = 105.chr
32
+ NOTIFY_LINESTATE_RESPONSE = 106.chr
33
+ NOTIFY_MODEMSTATE_RESPONSE = 107.chr
34
+ FLOWCONTROL_SUSPEND_RESPONSE = 108.chr
35
+ SET_LINESTATE_MASK_RESPONSE = 110.chr
36
+ SET_MODEMSTATE_MASK_RESPONSE = 111.chr
37
+ PURGE_DATA_RESPONSE = 112.chr
38
+
39
+ NONE = 1
40
+ ODD = 2
41
+ EVEN = 3
42
+ MARK = 4
43
+ SPACE = 5
44
+
45
+ SERIAL_PORT_PARAMS = %w{baud data_bits stop_bits parity}.freeze
46
+
47
+ class << self
48
+ def open(options)
49
+ sp = new(options)
50
+ if block_given?
51
+ begin
52
+ yield sp
53
+ ensure
54
+ sp.close
55
+ end
56
+ nil
57
+ else
58
+ nil
59
+ end
60
+ end
61
+ end
62
+
63
+ def initialize(options = {}, &block)
64
+ set_modem_params(options.slice(*SERIAL_PORT_PARAMS))
65
+
66
+ options['Binmode'] = true
67
+ options['Telnetmode'] = false
68
+ @telnet = Telnet.new(options, &block)
69
+ telnet.write(IAC + WILL + COM_PORT_OPTION)
70
+ sock.flush
71
+ @buffer = ''
72
+ readpartial(0)
73
+ end
74
+
75
+ def get_modem_params
76
+ @modem_params
77
+ end
78
+
79
+ def set_modem_params(modem_params)
80
+ @modem_params = modem_params.dup
81
+ @modem_params['baud'] = 115200 unless @modem_params.key?('baud')
82
+ @modem_params['data_bits'] = 8 unless @modem_params.key?('data_bits')
83
+ @modem_params['stop_bits'] = 1 unless @modem_params.key?('stop_bits')
84
+ @modem_params['parity'] = (data_bits == 8 ? NONE : EVEN)
85
+ write_modem_params if telnet
86
+ end
87
+
88
+ def baud
89
+ get_modem_params['baud']
90
+ end
91
+
92
+ def data_bits
93
+ get_modem_params['data_bits']
94
+ end
95
+
96
+ def stop_bits
97
+ get_modem_params['stop_bits']
98
+ end
99
+
100
+ def parity
101
+ get_modem_params['parity']
102
+ end
103
+
104
+ def sock
105
+ @telnet.sock
106
+ end
107
+
108
+ def read(length, outbuf = '')
109
+ readpartial(length, outbuf)
110
+ while outbuf.length < length
111
+ outbuf.concat(length - outbuf.length)
112
+ end
113
+ outbuf
114
+ end
115
+
116
+ def readpartial(length, outbuf = '')
117
+ loop do
118
+ # 0 is special and means 'read at least one control sequence'
119
+ break if length != 0 && @buffer.length != 0
120
+
121
+ data = sock.sysread([length - @buffer.length, 64 * 1024].max)
122
+
123
+ # avoid getting caught in the middle of a control sequence
124
+ while (data[-1] == IAC && sock.wait_readable(0))
125
+ data.concat(sock.sysread(16))
126
+ end
127
+
128
+ saw_control = false
129
+ data = @telnet.preprocess(data) do |control|
130
+ saw_control = true
131
+ if DO[0] == control[0] && COM_PORT_OPTION == control[1]
132
+ # start negotiation
133
+ write_modem_params
134
+ true
135
+ elsif DONT[0] == control[0] && COM_PORT_OPTION == control[1]
136
+ raise "Serial port control not supported"
137
+ false
138
+ else
139
+ false
140
+ end
141
+ end
142
+ @buffer.concat(data)
143
+ break if length == 0 && saw_control
144
+ end
145
+
146
+ length = [length, @buffer.length].min
147
+ outbuf.replace(@buffer[0...length])
148
+ @buffer = @buffer[length..-1]
149
+ outbuf
150
+ end
151
+
152
+ def ungetbyte(b)
153
+ @buffer.insert(0, b.chr)
154
+ end
155
+
156
+ def ungetc(c)
157
+ @buffer.insert(0, c)
158
+ end
159
+
160
+ def write(string)
161
+ string = string.gsub(/#{IAC}/no, IAC + IAC)
162
+ telnet.write(string)
163
+ end
164
+
165
+ def close
166
+ telnet.close
167
+ end
168
+
169
+ private
170
+
171
+ def write_modem_params
172
+ telnet.write(
173
+ IAC + SB + COM_PORT_OPTION + SET_BAUDRATE + [baud].pack("N") + IAC + SE +
174
+ IAC + SB + COM_PORT_OPTION + SET_DATASIZE + data_bits.chr + IAC + SE +
175
+ IAC + SB + COM_PORT_OPTION + SET_STOPSIZE + stop_bits.chr + IAC + SE +
176
+ IAC + SB + COM_PORT_OPTION + SET_PARITY + parity.chr + IAC + SE)
177
+ sock.flush
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,78 @@
1
+ module Net
2
+ class Telnet
3
+ module RFC2217::TelnetExtensions
4
+ def preprocess(string)
5
+ # combine CR+NULL into CR
6
+ string = string.gsub(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
7
+
8
+ # combine EOL into "\n"
9
+ string = string.gsub(/#{EOL}/no, "\n") unless @options["Binmode"]
10
+
11
+ # remove NULL
12
+ string = string.gsub(/#{NULL}/no, '') unless @options["Binmode"]
13
+
14
+ string.gsub(/#{IAC}(
15
+ [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|
16
+ [#{DO}#{DONT}#{WILL}#{WONT}]
17
+ [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{44.chr}#{OPT_EXOPL}]|
18
+ #{SB}[^#{IAC}]*#{IAC}#{SE}
19
+ )/xno) do
20
+ if block_given? && IAC != $1
21
+ # already handled; don't handle it ourselves
22
+ next '' if yield $1
23
+ end
24
+
25
+ if IAC == $1 # handle escaped IAC characters
26
+ IAC
27
+ elsif AYT == $1 # respond to "IAC AYT" (are you there)
28
+ self.write("nobody here but us pigeons" + EOL)
29
+ ''
30
+ elsif DO[0] == $1[0] # respond to "IAC DO x"
31
+ if OPT_BINARY[0] == $1[1]
32
+ unless @telnet_option["BINARY"] == true
33
+ @telnet_option["BINARY"] = true
34
+ self.write(IAC + WILL + OPT_BINARY)
35
+ end
36
+ else
37
+ self.write(IAC + WONT + $1[1..1])
38
+ end
39
+ ''
40
+ elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x"
41
+ self.write(IAC + WONT + $1[1..1])
42
+ ''
43
+ elsif WILL[0] == $1[0] # respond to "IAC WILL x"
44
+ if OPT_BINARY[0] == $1[1]
45
+ self.write(IAC + DO + OPT_BINARY)
46
+ elsif OPT_ECHO[0] == $1[1]
47
+ self.write(IAC + DO + OPT_ECHO)
48
+ elsif OPT_SGA[0] == $1[1]
49
+ unless @telnet_option["SGA"]
50
+ @telnet_option["SGA"] = true
51
+ self.write(IAC + DO + OPT_SGA)
52
+ end
53
+ else
54
+ self.write(IAC + DONT + $1[1..1])
55
+ end
56
+ ''
57
+ elsif WONT[0] == $1[0] # respond to "IAC WON'T x"
58
+ if OPT_ECHO[0] == $1[1]
59
+ self.write(IAC + DONT + OPT_ECHO)
60
+ elsif OPT_SGA[0] == $1[1]
61
+ unless @telnet_option["SGA"] == false
62
+ @telnet_option["SGA"] = false
63
+ self.write(IAC + DONT + OPT_SGA)
64
+ end
65
+ else
66
+ self.write(IAC + DONT + $1[1..1])
67
+ end
68
+ ''
69
+ elsif SB[0] == $1[0] # yield sub option
70
+ ''
71
+ else
72
+ ''
73
+ end
74
+ end
75
+ end # preprocess
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,7 @@
1
+ module Net
2
+ class Telnet
3
+ class RFC2217
4
+ VERSION = '0.0.1'
5
+ end
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: net-telnet-rfc2217
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Cody Cutrer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net-telnet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '9.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '9.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ description:
56
+ email: cody@cutrer.com'
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/net-telnet-rfc2217.rb
62
+ - lib/net/telnet/rfc2217.rb
63
+ - lib/net/telnet/rfc2217/telnet.rb
64
+ - lib/net/telnet/rfc2217/version.rb
65
+ homepage: https://github.com/ccutrer/net-telnet-2217
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.0.3
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Library for getting an IO-like object for a remote serial port
88
+ test_files: []