Module: NetConfGen::Packet

Defined in:
lib/netconfgen/netconfgen.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

Class Method Details

.parse(data) ⇒ Object

Parse a binary string into a packet. Does some sanity checking, can raise a ParseError.



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/netconfgen/netconfgen.rb', line 221

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