# -*- coding: binary -*-
module PacketFu

  # The Inject class handles injecting arrays of binary data on the wire.
  #
  # To inject single packets, use PacketFu::Packet.to_w() instead.
  class Inject
    attr_accessor :array, :stream, :show_live # Leave these public and open.
    attr_reader :iface, :snaplen, :promisc, :timeout # Cant change after the init.

    def initialize(args={})
      @array = [] # Where the packet array goes.
      @stream = [] # Where the stream goes.
      @iface = args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo" 
      @snaplen = args[:snaplen] || 0xffff
      @promisc = args[:promisc] || false # Sensible for some Intel wifi cards
      @timeout = args[:timeout] || 1
      @show_live = nil
    end

    # Takes an array, and injects them onto an interface. Note that
    # complete packets (Ethernet headers on down) are expected.
    #
    # === Parameters
    #
    #   :array || arr
    #    An array of binary data (usually packet.to_s style).
    #   :int || sleep
    #    Number of seconds to sleep between injections (in float format)
    #   :show_live || :live
    #    If true, puts data about what was injected to stdout.
    #
    # === Example
    #
    #  inj = PacketFu::Inject.new
    #  inj.array_to_wire(:array => [pkt1, pkt2, pkt3], :sleep => 0.1)
    #
    def array_to_wire(args={})
      pkt_array = args[:array] || args[:arr] || @array
      interval = args[:int] || args[:sleep]
      show_live = args[:show_live] || args[:live] || @show_live

      @stream = Pcap.open_live(@iface,@snaplen,@promisc,@timeout)
      pkt_count = 0
      pkt_array.each do |pkt|
        @stream.inject(pkt)
        sleep interval if interval
        pkt_count +=1
        puts "Sent Packet \##{pkt_count} (#{pkt.size})" if show_live
      end
      # Return # of packets sent, array size, and array total size
      [pkt_count, pkt_array.size, pkt_array.join.size]
    end

    # Equivalent to array_to_wire
    def a2w(args={})
      array_to_wire(args)
    end

    # Equivalent to array_to_wire
    def inject(args={})
      array_to_wire(args)
    end

  end
end
