modem_protocols 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/modem_protocols.rb +322 -0
  2. data/test/test_xmodem.rb +241 -0
  3. metadata +56 -0
@@ -0,0 +1,322 @@
1
+ # Author:: Jonno Downes (jonno@jamtronix.com)
2
+ # License:: Mozilla Public License 1.1
3
+
4
+
5
+ require 'log4r'
6
+ include Log4r
7
+
8
+ module ModemProtocols
9
+
10
+ XMODEM_BLOCK_SIZE=128 #how many bytes (ecluding header & checksum) in each block?
11
+ XMODEM_MAX_TIMEOUTS=5 #how many timeouts in a row before the sender gives up?
12
+ XMODEM_MAX_ERRORS=10 #how many errors on a single block before the receiver gives up?
13
+
14
+ XMODEM_CRC_ATTEMPTS=3 #how many times should receiver attempt to use CRC?
15
+ LOG_NAME='ModemProtocols'
16
+ @timeout_seconds=5.0 #default timeout period
17
+
18
+ #how long does the protocol wait before giving up?
19
+ def ModemProtocols::timeout_seconds
20
+ @timeout_seconds
21
+ end
22
+
23
+ def ModemProtocols::timeout_seconds=(val)
24
+ @timeout_seconds=val
25
+ end
26
+
27
+
28
+
29
+
30
+ # receive a file using XMODEM protocol (block size = 128 bytes)
31
+ # remote:: must be an IO object connected to an XMODEM sender
32
+ # local:: must be an IO object - the inbound file (trimmed of any final padding) will be written to this
33
+ # options:: hash of options. options are: values :crc (use 16bit CRC instead of 8 bit checksum)
34
+ # - :mode=> :crc or :checksum (default is 8 bit checksum)
35
+ #
36
+
37
+ def ModemProtocols::xmodem_rx(remote,local,options=nil)
38
+
39
+
40
+ mode = ( (options.nil?) || options[:mode].nil? ) ? :checksum : options[:mode]
41
+
42
+ logger.debug "rx: XMODEM - #{mode}"
43
+ #flush the input buffer
44
+ loop do
45
+ break if (select([remote],nil,nil,0.01).nil?)
46
+ remote.getc
47
+ end
48
+
49
+
50
+ #trigger sending
51
+ case mode
52
+ when :crc
53
+ XMODEM_CRC_ATTEMPTS.times do |attempt|
54
+ remote.putc('C')
55
+ break unless (select([remote],nil,nil,timeout_seconds).nil?)
56
+ #if we don't get a response, fall back to checksum mode
57
+ if attempt==XMODEM_CRC_ATTEMPTS-1 then
58
+ logger.warn "rx: crc-16 request failed, falling back to checksum mode"
59
+ remote.putc(NAK)
60
+ mode=:checksum
61
+ end
62
+ end
63
+ else
64
+ remote.putc(NAK)
65
+ end
66
+
67
+ expected_block=1
68
+ error_count=0
69
+ last_block=""
70
+ data=""
71
+ loop do
72
+
73
+ begin
74
+ rx_cmd=xmodem_rx_getbyte(remote)
75
+
76
+ if rx_cmd==EOT then
77
+ remote.putc(ACK)
78
+ trimmed_block=last_block.sub(/(\x1A+)\Z/,'')
79
+ local<< trimmed_block#trim any trailing FILLER characters in last block
80
+ break
81
+ end
82
+
83
+ if rx_cmd!=SOH then
84
+ logger.warn "rx: expected SOH (0x#{SOH}) got 0x#{"%x" % rx_cmd} - pos = #{remote.pos}"
85
+ next
86
+ end
87
+
88
+ data=""
89
+ block=xmodem_rx_getbyte(remote)
90
+ block_check=xmodem_rx_getbyte(remote)
91
+ validity=:valid
92
+ validity=:invalid unless (block_check+block)==0xFF
93
+
94
+ logger.debug "rx: #{validity} block number 0x#{"%02x" % block} / block number check 0x#{"%02x" % block_check}"
95
+ logger.debug "rx: receiving block #{block} / expected block #{expected_block}"
96
+ raise RXSynchError if block!=expected_block && block!=((expected_block-1) % 0x100)
97
+
98
+ if (block==expected_block) && (validity==:valid) then
99
+ local<<last_block
100
+ last_block=""
101
+ end
102
+ XMODEM_BLOCK_SIZE.times do
103
+ b=(xmodem_rx_getbyte(remote))
104
+ data<<b
105
+ Thread.pass
106
+ end
107
+
108
+
109
+ check_ok=false
110
+
111
+ case mode
112
+ when :crc
113
+ rx_crc=(xmodem_rx_getbyte(remote)<<8)+xmodem_rx_getbyte(remote)
114
+ crc=ccitt16_crc(data)
115
+ check_ok=(crc==rx_crc)
116
+ if !check_ok then
117
+ logger.warn "invalid crc-16 for block #{block}: calculated 0x#{'%04x' % crc}, got 0x#{'%02x' % rx_crc}"
118
+ end
119
+ else
120
+ rx_checksum=xmodem_rx_getbyte(remote)
121
+ checksum=xmodem_checksum(data)
122
+ check_ok=(checksum==rx_checksum)
123
+ if !check_ok then
124
+ logger.warn "invalid checksum for block #{block}: calculated 0x#{'%02x' % checksum}, got 0x#{'%02x' % rx_checksum}"
125
+ end
126
+ end
127
+
128
+ if (check_ok) then
129
+ last_block=data
130
+ logger.debug "rx: #{mode} test passed for block #{block}"
131
+ remote.putc(ACK)
132
+ if (block==expected_block) then
133
+ expected_block=((expected_block+1) % 0x100)
134
+ error_count=0 #reset the error count
135
+ end
136
+ else
137
+ remote.putc(NAK)
138
+ error_count+=1
139
+ logger.warn "rx: checksum error # #{error_count} / max #{XMODEM_MAX_ERRORS}"
140
+ raise RXChecksumError.new("too many receive errors on block #{block}") if error_count>XMODEM_MAX_ERRORS
141
+ end
142
+ rescue RXTimeout
143
+ error_count+=1
144
+ logger.warn "rx: timeout error # #{error_count} / max #{XMODEM_MAX_ERRORS}"
145
+ raise RXTimeout("too many receive errors on block #{block}").new if error_count>XMODEM_MAX_ERRORS
146
+ end
147
+ end
148
+
149
+ logger.info "receive complete"
150
+ end
151
+
152
+ # send a file using standard XMODEM protocol (block size = 128 bytes)
153
+ # will use CRC mode if requested by sender, else use 8-bit checksum
154
+ # remote:: must be an IO object connected to an XMODEM receiver
155
+ # local:: must be an IO object containing the data to be sent
156
+ def ModemProtocols::xmodem_tx(remote,local)
157
+ block_number=1
158
+ current_block=""
159
+ sent_eot=false
160
+
161
+ XMODEM_BLOCK_SIZE.times do
162
+ b=(local.eof? ? FILLER : local.getc)
163
+ current_block<<b.chr
164
+ Thread.pass
165
+ end
166
+ checksum=xmodem_checksum(current_block)
167
+ mode=:checksum
168
+ loop do
169
+ logger.info "tx: waiting for ACK/NAK/CAN (eot_sent: #{sent_eot})"
170
+ if select([remote],nil,nil,timeout_seconds*XMODEM_MAX_TIMEOUTS).nil? then
171
+ raise RXTimeout.new("timeout waiting for input on tx (#{timeout_seconds*XMODEM_MAX_TIMEOUTS} seconds)") unless sent_eot
172
+ logger.info "tx: timeout waiting for ACK of EOT"
173
+ return
174
+ end
175
+ if remote.eof? then
176
+ logger.warn "tx: unexpected eof on input"
177
+ break
178
+ end
179
+ tx_cmd=remote.getc
180
+ logger.debug "tx: got 0x#{"%x" % tx_cmd}"
181
+ if tx_cmd==ACK then
182
+ if sent_eot then
183
+ logger.debug "tx: got ACK of EOT"
184
+ break
185
+ end
186
+
187
+ if local.eof? then
188
+ remote.putc(EOT)
189
+ logger.debug "tx: got ACK of last block"
190
+ sent_eot=true
191
+ next
192
+ end
193
+ block_number=((block_number+1)%0x100)
194
+ current_block=""
195
+ XMODEM_BLOCK_SIZE.times do
196
+ b=(local.eof? ? FILLER : local.getc)
197
+ current_block<<b
198
+ Thread.pass
199
+ end
200
+
201
+ elsif (block_number==1) && (tx_cmd==CRC_MODE) then
202
+ mode=:crc
203
+ logger.debug "tx: using crc-16 mode"
204
+ end
205
+
206
+ next unless [ACK,NAK,CRC_MODE].include?(tx_cmd)
207
+ logger.info "tx: sending block #{block_number}"
208
+ remote.putc(SOH) #start of block
209
+ remote.putc(block_number) #block number
210
+ remote.putc(0xff-block_number) #1's complement of block number
211
+ current_block.each_byte {|b| remote.putc(b)}
212
+ case mode
213
+ when :crc then
214
+ crc=ccitt16_crc(current_block)
215
+ remote.putc(crc>>8) #crc hi byte
216
+ remote.putc(crc & 0xFF) #crc lo byte
217
+ logger.debug "tx: crc-16 for block #{block_number}:#{ "%04x" % crc}"
218
+ else
219
+ checksum=xmodem_checksum(current_block)
220
+ remote.putc(checksum)
221
+ logger.debug "tx: checksum for block #{block_number}:#{ "%02x" % checksum}"
222
+ end
223
+
224
+ end
225
+ logger.info "transmit complete (eot_sent: #{sent_eot})"
226
+ end
227
+
228
+ #calculate an 8-bit XMODEM checksum
229
+ #this is just the sum of all bytes modulo 0x100
230
+ def ModemProtocols::xmodem_checksum(block)
231
+ raise RXChecksumError("checksum requested of invalid block {size should be #{XMODEM_BLOCK_SIZE}, was #{block.length}") unless block.length==XMODEM_BLOCK_SIZE
232
+ checksum=0
233
+ block.each_byte do |b|
234
+ checksum=(checksum+b)%0x100
235
+ end
236
+ checksum
237
+ end
238
+
239
+ #calculate a 16-bit CRC
240
+ def ModemProtocols::ccitt16_crc(block)
241
+ #cribbed from http://www.hadermann.be/blog/32/ruby-crc16-implementation/
242
+ raise RXChecksumError("checksum requested of invalid block {size should be #{XMODEM_BLOCK_SIZE}, was #{block.length}") unless block.length==XMODEM_BLOCK_SIZE
243
+ crc=0
244
+ block.each_byte{|x| crc = ((crc<<8) ^ CCITT_16[(crc>>8) ^ x])&0xffff}
245
+ crc
246
+ end
247
+
248
+ private
249
+
250
+ SOH = 0x01
251
+ STX = 0x02
252
+ EOT = 0x04
253
+ ACK = 0x06
254
+ NAK = 0x15
255
+ CAN = 0x18
256
+ CRC_MODE=0x43 #'C'
257
+ FILLER = 0x1A
258
+
259
+
260
+ CCITT_16 = [
261
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
262
+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
263
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
264
+ 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
265
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
266
+ 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
267
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
268
+ 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
269
+ 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
270
+ 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
271
+ 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
272
+ 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
273
+ 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
274
+ 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
275
+ 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
276
+ 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
277
+ 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
278
+ 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
279
+ 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
280
+ 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
281
+ 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
282
+ 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
283
+ 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
284
+ 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
285
+ 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
286
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
287
+ 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
288
+ 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
289
+ 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
290
+ 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
291
+ 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
292
+ 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
293
+ ]
294
+
295
+
296
+
297
+ def ModemProtocols::xmodem_rx_getbyte(remote)
298
+
299
+ if (select([remote],nil,nil,timeout_seconds).nil?) then
300
+ remote.putc(NAK)
301
+ raise RXTimeout
302
+ end
303
+ raise RXSynchError if remote.eof?
304
+ remote.getc
305
+ end
306
+
307
+
308
+ def ModemProtocols::logger
309
+ Logger.new(LOG_NAME) if Logger[LOG_NAME].nil?
310
+ Logger[LOG_NAME]
311
+ end
312
+
313
+ class RXTimeout < RuntimeError
314
+ end
315
+
316
+ class RXChecksumError < RuntimeError
317
+ end
318
+
319
+ class RXSynchError < RuntimeError
320
+ end
321
+
322
+ end
@@ -0,0 +1,241 @@
1
+
2
+ #make sure the relevant folder with our libraries is in the require path
3
+ lib_path=File.expand_path(File.dirname(__FILE__)+"//..//lib")
4
+ $:.unshift(lib_path) unless $:.include?(lib_path)
5
+
6
+
7
+ require 'modem_protocols'
8
+ require 'test/unit'
9
+ require 'socket'
10
+
11
+
12
+ Thread.abort_on_exception = true
13
+
14
+
15
+ ModemProtocols::logger.outputters = Outputter.stdout
16
+
17
+
18
+ ModemProtocols::timeout_seconds=0.4 #so we don't wait so long for retransmissions
19
+ LOCAL_PORT=9999
20
+
21
+
22
+ module CorruptIn
23
+ attr_accessor :real_getc,:corruption_frequency
24
+
25
+ def getc
26
+ @char_count=0 if @char_count.nil?
27
+
28
+ raise "real_getc not initialised" if @real_getc.nil?
29
+ b=@real_getc.call
30
+ @char_count+=1
31
+ if ((@char_count % @corruption_frequency)==0) then
32
+ corrupted_char=0xff-b
33
+ $stdout.puts "corrupting : 0x%02x -> 0x%02x" % [b,corrupted_char]
34
+ b=corrupted_char
35
+ end
36
+ return b
37
+ end
38
+
39
+ end
40
+
41
+ module CorruptOut
42
+ attr_accessor :real_putc,:corruption_frequency
43
+
44
+ def putc (b)
45
+ @char_count=0 if @char_count.nil?
46
+
47
+ raise "real_putc not initialised" if @real_putc.nil?
48
+ @char_count+=1
49
+ if ((@char_count % @corruption_frequency)==0) then
50
+ corrupted_char=0xff-b
51
+ $stdout.puts "corrupting : 0x%02x -> 0x%02x" % [b,corrupted_char]
52
+ b=corrupted_char
53
+ end
54
+ @real_putc.call(b)
55
+
56
+ end
57
+ end
58
+
59
+
60
+ module DropIn
61
+ attr_accessor :real_getc,:drop_frequency
62
+
63
+ def getc
64
+ @char_count=0 if @char_count.nil?
65
+
66
+ raise "real_getc not initialised" if @real_getc.nil?
67
+ b=@real_getc.call
68
+ @char_count+=1
69
+ if ((@char_count % @drop_frequency)==0) then
70
+ $stdout.puts "dropping : 0x%02x " % [b]
71
+ @real_getc.call
72
+ end
73
+ return b
74
+ end
75
+ end
76
+
77
+ module DropOut
78
+ attr_accessor :real_putc,:drop_frequency
79
+
80
+ def putc (b)
81
+ @char_count=0 if @char_count.nil?
82
+
83
+ raise "real_putc not initialised" if @real_putc.nil?
84
+ @char_count+=1
85
+ if ((@char_count % @drop_frequency)==0) then
86
+ $stdout.puts "dropping : 0x%02x " % [b]
87
+ else
88
+ @real_putc.call(b)
89
+ end
90
+ end
91
+ end
92
+
93
+
94
+ class XmodemTests< Test::Unit::TestCase
95
+
96
+
97
+ def test_checksum
98
+ assert_equal(0,ModemProtocols::xmodem_checksum( "\000"*128))
99
+ assert_equal(128,ModemProtocols::xmodem_checksum("\001"*128))
100
+ assert_equal(0,ModemProtocols::xmodem_checksum("\002"*128))
101
+ assert_equal(128,ModemProtocols::xmodem_checksum("\003"*128))
102
+
103
+
104
+ end
105
+
106
+ @@server=nil
107
+ def sendfile(file)
108
+ if @@server.nil? then
109
+ @@server = TCPServer.new('localhost', LOCAL_PORT)
110
+ else
111
+ puts "reusing existing server"
112
+ end
113
+ session = @@server.accept
114
+ session.sync=true
115
+ puts "Connected (sendfile)"
116
+ ModemProtocols::xmodem_tx(session,file)
117
+ session.close
118
+
119
+ end
120
+
121
+ def acceptfile(file,error_type=nil,error_frequency=nil,rx_options=nil)
122
+ socket=TCPSocket.new('localhost', LOCAL_PORT)
123
+ socket.sync=true
124
+ puts "Connected (acceptfile)"
125
+ if !error_frequency.nil? then
126
+ real_getc=socket.method(:getc)
127
+
128
+ case error_type
129
+ when :corruption_in
130
+ real_getc=socket.method(:getc)
131
+ socket.extend(CorruptIn)
132
+ socket.corruption_frequency=error_frequency
133
+ socket.real_getc=real_getc
134
+ when :packet_loss_in
135
+ real_getc=socket.method(:getc)
136
+ socket.extend(DropIn)
137
+ socket.drop_frequency=error_frequency
138
+ socket.real_getc=real_getc
139
+ when :packet_loss_out
140
+ real_putc=socket.method(:putc)
141
+ socket.extend(DropOut)
142
+ socket.drop_frequency=error_frequency
143
+ socket.real_putc=real_putc
144
+ when :corruption_out
145
+ real_putc=socket.method(:putc)
146
+ socket.extend(CorruptOut)
147
+ socket.corruption_frequency=error_frequency
148
+ socket.real_putc=real_putc
149
+ else
150
+ raise "unknown error_type #{error_type}"
151
+ end
152
+ file.flush
153
+ end
154
+ ModemProtocols::xmodem_rx(socket,file,rx_options)
155
+ loop {Thread.pass} until socket.closed?
156
+
157
+ end
158
+
159
+ def do_test(tx_file,rx_file,error_type=nil,error_frequency=nil,rx_options=nil)
160
+ test_description="test type: #{error_type}"
161
+ test_description+=" (freq=#{error_frequency})" unless error_frequency.nil?
162
+ made_tx=false
163
+ made_rx=false
164
+ if !(tx_file.respond_to?(:getc))
165
+ tx_filename=tx_file
166
+ tx_file=File.new(tx_filename,"rb")
167
+ else
168
+ tx_filename=tx_file.class
169
+ tx_file.rewind
170
+ end
171
+
172
+
173
+ if !(rx_file.respond_to?(:putc))
174
+ rx_filename=rx_file
175
+ rx_file=File.new(rx_filename,"wb+")
176
+ else
177
+ rx_filename=rx_file.class
178
+ rx_file.rewind
179
+ end
180
+ puts "#{test_description} : #{tx_filename}->#{rx_filename}"
181
+
182
+
183
+ tx_thread=Thread.new {sendfile(tx_file)}
184
+ rx_thread=Thread.new {acceptfile(rx_file,error_type,error_frequency,rx_options)}
185
+ loop do
186
+ break unless tx_thread.alive?
187
+ break unless rx_thread.alive?
188
+ sleep(0.01) #wake up occasionally to get keyboard input, so we break on ^C
189
+ end
190
+ tx_file.rewind
191
+ rx_file.rewind
192
+ rx_filecontents=rx_file.read
193
+ tx_filecontents=tx_file.read
194
+ assert_equal(tx_filecontents.length,rx_filecontents.length,"file length correct after round trip")
195
+ assert_equal(tx_filecontents,rx_filecontents,"file contents correct after round trip")
196
+
197
+ tx_file.close if made_tx
198
+ rx_file.close if made_rx
199
+
200
+ end
201
+
202
+ def test_all
203
+ sample_text_file="sample.test.txt"
204
+ sample_bin_file="sample.test.bin"
205
+ f=File.new(sample_text_file,"w")
206
+ f<<File.new(__FILE__,"r").read
207
+ f.close
208
+
209
+ f=File.new(sample_bin_file,"wb")
210
+ 2000.times {|i| f<<(i%0x100).chr}
211
+ f.close
212
+
213
+ txstring_io=StringIO.new("this is a test string")
214
+ rxstring_io=StringIO.new("")
215
+
216
+ do_test(sample_text_file,"crc-simple.test.txt",nil,nil,{:mode=>:crc})
217
+ do_test(txstring_io,rxstring_io)
218
+ do_test(sample_text_file,"corrupt-crc.test.txt",:corruption_in,700,{:mode=>:crc})
219
+
220
+
221
+ do_test(txstring_io,rxstring_io)
222
+ do_test(sample_text_file,rxstring_io)
223
+ do_test(sample_text_file,"simple.test.txt")
224
+ do_test(sample_bin_file,"corrupt_out.test.bin",:corruption_out,4)
225
+ do_test(sample_text_file,"packet_loss_out.test.txt",:packet_loss_out,3)
226
+ do_test(sample_text_file,"packet_loss_in.test.txt",:packet_loss_in,200)
227
+
228
+
229
+ do_test(sample_text_file,"corrupt.test.txt",:corruption_in,700)
230
+ do_test(sample_text_file,"very_corrupt.test.txt",:corruption_in,200)
231
+
232
+ do_test(sample_bin_file,"simple.test.bin")
233
+ do_test(sample_bin_file,"corrupt.test.bin",:corruption_in,700)
234
+
235
+ bigstring=""
236
+ 512.times {|i| bigstring<<((i%0x100).chr*128)}
237
+ do_test(StringIO.new(bigstring),"bigfile.test.txt")
238
+
239
+ end
240
+ end
241
+
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: modem_protocols
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jonno Downes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-29 00:00:00 +11:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: jonno@jamtronix.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/modem_protocols.rb
26
+ - test/test_xmodem.rb
27
+ has_rdoc: true
28
+ homepage: http://petboardstuff.rubyforge.org
29
+ licenses: []
30
+
31
+ post_install_message:
32
+ rdoc_options: []
33
+
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ requirements: []
49
+
50
+ rubyforge_project:
51
+ rubygems_version: 1.3.5
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: a pure ruby implementation of XMODEM
55
+ test_files: []
56
+