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.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/netconfgen/netconfgen.rb', line 138

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