require 'strscan' class PacketViaDMEM PACKET = /^(Received|Sent) \d+ byte parcel:.*\n/ FAKE = { :dmac => %w( 22 22 22 22 22 22 ), :smac => %w( 66 66 66 66 66 66 ), :etype => %w( 88 47 ), } HEADER_SIZE = { :received => 6, :sent => 13, } class Error < StandardError; end def initialize opts={} @received = opts.delete :received @sent = opts.delete :sent @received ||= HEADER_SIZE[:received] @sc = StringScanner.new '' end def parse str packets = [] headers = [] @sc.string = str while @sc.scan_until PACKET match = @sc.matched.split(/\s+/) type = match.first.downcase.to_sym next if type == :received and (not @received or @received < 1) next if type == :sent and (not @sent or @sent < 1) @sc.scan_until(/\n/) if type == :received pkt = '' while @sc.match?(/^0x/) pkt << @sc.scan_until(/\n/).strip end pkt = parse_packet pkt pop, push = get_pop_push(type, pkt) header = pkt[0..pop-1] pkt = pkt[pop..-1] if pkt packets << '000000 ' + [push, pkt].flatten.join(' ') headers << header.join(' ') end end [packets, headers] end private def get_pop_push type, pkt push = [] pop = if type == :sent case pkt.first.to_i(16) when 0x00 # we're sending to fabric # we may send MAC to fabric,byte 6, 7, 9, 11, 21? if pkt[5].to_i(16) == 0xf0 # we don't send MAC to fabric push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype] 24 else # we send MAC to fabric 33 end when 0x08 then 13 else @sent end else case pkt.first.to_i(16) when 0x00 then 6 #1,2,3,4,5,6 when 0x10 then 8 #1,2,3,4,7,8,5,6 else @received end end [pop, push] end def parse_packet pkt pkt = pkt.gsub(/0x/, '') pkt = pkt.gsub(/\s+/, '') pkt = pkt.scan(/../) pkt end end