lendist.rb
#-------------------------------------------------------------------------
# Packet Lengths
#   Packet Length distribution
#
# You may use this code freely in your commercial and non-commercial work.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
#
# Copyright (c) Unleash Networks 2005, All rights reserved
#----------------------------------------------------------------------------
require 'rubygems'
require 'win32ole'
require 'fox16'
include Fox
require 'UnleashCharts'
include UnleashCharts
 
class ChartWindow < FXMainWindow
 
	def initialize(theapp)
 
			# base class
			super(theapp, "Packet Length Distribution", nil, nil, DECOR_ALL,
						0,0,600,300)
 
			# single horizontal panel
			@contents = FXHorizontalFrame.new(self,
				LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0,0,0,0,0,0)
 
			# vertical frame
			@canvasFrame = FXVerticalFrame.new(@contents,
				LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT,
				0,0,0,0,10,10,10,10)
 
			# label above canvas
			@label = FXLabel.new(@canvasFrame, "Distribution of packet lengths",
									nil, JUSTIFY_CENTER_X|LAYOUT_FILL_X)
 
			# divider
			FXHorizontalSeparator.new(@canvasFrame)
 
			# actual canvas (whew!)
			@canvas = UnBarChart.new(@canvasFrame)
 
	end
 
 
	def create
		super
		show(PLACEMENT_SCREEN)
	end	
 
 
	def setModel (mod)
		@canvas.model = mod
	end
 
end
 
 
class PacketLengthBuckets
 
	@maxPacketSize = 2000
	@bucket
	@gran	
 
	attr_reader	:barcount, :maxval
 
	def initialize(maxpacketsize,granularity)
		@maxPacketSize = maxpacketsize
		@gran = granularity
		@bucket = Array.new(maxpacketsize/granularity)
		@bucket.fill(0)
		@barcount = @bucket.length
		@maxval = 100
	end
 
	def loadCaptureFile(filename)
		unsniffDB = WIN32OLE.new("Unsniff.Database")
		unsniffDB.OpenForRead(filename)
		packetIndex = unsniffDB.PacketIndex
		(0..packetIndex.Count-1).each do |idx|
			pkt = packetIndex.Item(idx)
			bucketid = pkt.Length / @gran
			@bucket[bucketid] += 1
		end
		@maxval = packetIndex.Count
 
		unsniffDB.Close
	end
 
	def dumpContents
		@bucket.each_index do |idx|
			bitem = @bucket[idx]
			print " [#{idx}]\t #{bitem}\n"
		end
	end
 
	def each_label_x  
		(0..@bucket.length-1).each do |idx|
			from = idx * @gran
			to = (idx+1) * @gran
			labtext = "< #{to}"
			labval = idx
			yield labtext, labval
		end
	end
 
	def each_val
		(0..@bucket.length-1).each do |idx|
			value_y = @bucket[idx]
			yield  idx, value_y
		end
	end
 
 
end
 
 
USAGE = "lendist <capture-filename> "
 
if ARGV.length != 1
	puts USAGE
	exit 1
end
 
lenBuckets = PacketLengthBuckets.new(2000,200)
lenBuckets.loadCaptureFile(ARGV[0])
lenBuckets.dumpContents
 
# A new Fox Application and MainWindow object
theApp = FXApp.new
theMainWindow = ChartWindow.new(theApp)
 
theMainWindow.setModel(lenBuckets)
 
# Run application
theApp.create
theMainWindow.show
theApp.run