Module: TFTP::Packet
- Defined in:
- lib/tftp/tftp.rb
Overview
Packet can parse a binary string into a lightweight object representation.
Defined Under Namespace
Classes: ACK, Base, DATA, ERROR, RRQ, WRQ
Class Method Summary collapse
-
.parse(data) ⇒ Object
Parse a binary string into a packet.
Class Method Details
.parse(data) ⇒ Object
Parse a binary string into a packet. Does some sanity checking, can raise a ParseError.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/tftp/tftp.rb', line 57 def self.parse(data) data = data.force_encoding('ascii-8bit') opcode = data.unpack('n').first if opcode < 1 || opcode > 5 raise ParseError, "Unknown packet opcode '#{opcode.inspect}'" end payload = data.slice(2, data.length - 2) case opcode when 1, 2 # rrq, wrq raise ParseError, 'Not null terminated' if payload.slice(payload.length - 1) != "\x00" xs = payload.split("\x00") raise ParseError, "Not enough elements: #{xs.inspect}" if xs.length < 2 filename = xs[0] mode = xs[1].downcase.to_sym raise ParseError, "Unknown mode '#{xs[1].inspect}'" unless [:netascii, :octet].member? mode return RRQ.new(filename, mode) if opcode == 1 return WRQ.new(filename, mode) when 3 # data seq = payload.unpack('n').first block = payload.slice(2, payload.length - 2) || '' raise ParseError, "Exceeded block length with #{block.length} bytes" if block.length > 512 return DATA.new(seq, block) when 4 # ack raise ParseError, "Wrong payload length with #{payload.length} bytes" if payload.length != 2 seq = payload.unpack('n').first return ACK.new(seq) when 5 # error raise ParseError, 'Not null terminated' if payload.slice(payload.length - 1) != "\x00" code = payload.unpack('n').first raise ParseError, "Unknown error code '#{code.inspect}'" if code < 0 || code > 7 msg = payload.slice(2, payload.length - 3) || '' return ERROR.new(code, msg) end end |