solutious-stella 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +36 -0
- data/README.textile +162 -0
- data/Rakefile +88 -0
- data/bin/stella +12 -0
- data/bin/stella.bat +12 -0
- data/lib/daemonize.rb +56 -0
- data/lib/pcaplet.rb +180 -0
- data/lib/stella.rb +101 -0
- data/lib/stella/adapter/ab.rb +337 -0
- data/lib/stella/adapter/base.rb +106 -0
- data/lib/stella/adapter/httperf.rb +305 -0
- data/lib/stella/adapter/pcap_watcher.rb +221 -0
- data/lib/stella/adapter/proxy_watcher.rb +76 -0
- data/lib/stella/adapter/siege.rb +341 -0
- data/lib/stella/cli.rb +258 -0
- data/lib/stella/cli/agents.rb +73 -0
- data/lib/stella/cli/base.rb +55 -0
- data/lib/stella/cli/language.rb +18 -0
- data/lib/stella/cli/localtest.rb +78 -0
- data/lib/stella/cli/sysinfo.rb +16 -0
- data/lib/stella/cli/watch.rb +278 -0
- data/lib/stella/command/base.rb +40 -0
- data/lib/stella/command/localtest.rb +358 -0
- data/lib/stella/data/domain.rb +82 -0
- data/lib/stella/data/http.rb +131 -0
- data/lib/stella/logger.rb +84 -0
- data/lib/stella/response.rb +85 -0
- data/lib/stella/storable.rb +201 -0
- data/lib/stella/support.rb +276 -0
- data/lib/stella/sysinfo.rb +257 -0
- data/lib/stella/test/definition.rb +79 -0
- data/lib/stella/test/run/summary.rb +70 -0
- data/lib/stella/test/stats.rb +114 -0
- data/lib/stella/text.rb +64 -0
- data/lib/stella/text/resource.rb +38 -0
- data/lib/utils/crypto-key.rb +84 -0
- data/lib/utils/domainutil.rb +47 -0
- data/lib/utils/escape.rb +302 -0
- data/lib/utils/fileutil.rb +78 -0
- data/lib/utils/httputil.rb +266 -0
- data/lib/utils/mathutil.rb +15 -0
- data/lib/utils/stats.rb +88 -0
- data/lib/utils/textgraph.rb +267 -0
- data/lib/utils/timerutil.rb +58 -0
- data/lib/win32/Console.rb +970 -0
- data/lib/win32/Console/ANSI.rb +305 -0
- data/support/kvm.h +91 -0
- data/support/ruby-pcap-takuma-notes.txt +19 -0
- data/support/ruby-pcap-takuma-patch.txt +30 -0
- data/support/text/en.yaml +80 -0
- data/support/text/nl.yaml +7 -0
- data/support/useragents.txt +75 -0
- data/tests/01-util_test.rb +0 -0
- data/tests/02-stella-util_test.rb +42 -0
- data/tests/10-stella_test.rb +104 -0
- data/tests/11-stella-storable_test.rb +68 -0
- data/tests/60-stella-command_test.rb +248 -0
- data/tests/80-stella-cli_test.rb +45 -0
- data/tests/spec-helper.rb +31 -0
- metadata +165 -0
data/CHANGES.txt
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
STELLA, CHANGES
|
2
|
+
|
3
|
+
|
4
|
+
#### 0.5.5 (2009-01-14) ###############################
|
5
|
+
|
6
|
+
http://github.com/solutious/stella/tree/0.5.5
|
7
|
+
|
8
|
+
* Now has specs (33 specifications, 303 requirements)
|
9
|
+
* New dependency: test-spec (development copy only)
|
10
|
+
* Added delano/drydock to vendor (was delano/frylock).
|
11
|
+
* Improved argument handling for load tool adapters (httperf not complete)
|
12
|
+
* Re-built Stella::Storable and subclasses (now using "field" method)
|
13
|
+
* Test::Stats, Test::Run::Summary cleanup
|
14
|
+
* Fixed RubyGems require error
|
15
|
+
* Fixed stddev bug by removing weak math, adding stats class from Mongrel
|
16
|
+
* Fixed --agent error
|
17
|
+
|
18
|
+
|
19
|
+
#### 0.5.4-alpha (2009-01-07) #########################
|
20
|
+
|
21
|
+
http://github.com/solutious/stella/tree/0.5.4-alpha
|
22
|
+
|
23
|
+
* New command: watch. Monitor HTTP traffic with Ruby-Pcap (unix only) or proxy. Pcap also supports DNS sniffing.
|
24
|
+
* Improved error handling for stats output
|
25
|
+
* Now runs on Ruby 1.9.1, JRuby
|
26
|
+
* Added Windows support for most features
|
27
|
+
* Added patch for Ruby-Pcap
|
28
|
+
* Added friendly error handling for Apache Bench, Siege, and Httperf
|
29
|
+
|
30
|
+
|
31
|
+
#### 0.5.3-preview (2008-12-23) #######################
|
32
|
+
|
33
|
+
http://github.com/solutious/stella/tree/e4d2bd8db3d1323fbc3b8bbb7f703ce7b8c88551
|
34
|
+
|
35
|
+
* Initial public release
|
36
|
+
|
data/README.textile
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
h1. Stella - Your Performance Testing Friend
|
2
|
+
|
3
|
+
Release: 0.5.5 (2009-01-14)
|
4
|
+
|
5
|
+
This is a BETA release. Proceed in double verify mode!
|
6
|
+
|
7
|
+
h2. Overview
|
8
|
+
|
9
|
+
Stella is a command-line tool for running, reporting, and analyzing performance tests.
|
10
|
+
|
11
|
+
|
12
|
+
h2. Prerequisites
|
13
|
+
|
14
|
+
* Linux, BSD, Solaris
|
15
|
+
* Ruby 1.8.x, 1.9.x, or JRuby 1.1
|
16
|
+
* Native Libraries (c or c++)
|
17
|
+
** Pcap (optional, for packet sniffing)
|
18
|
+
* Ruby Libraries
|
19
|
+
** rspec
|
20
|
+
** net-dns
|
21
|
+
** Ruby-Pcap (optional, for packet sniffing)
|
22
|
+
|
23
|
+
* One of:
|
24
|
+
** "Apache Bench":http://httpd.apache.org/docs/2.2/programs/ab.html
|
25
|
+
** "Siege":http://www.joedog.org/index/siege-home
|
26
|
+
** "Httperf":http://www.hpl.hp.com/research/linux/httperf/
|
27
|
+
*** _Note: Argument handling for Httperf is incomplete_
|
28
|
+
|
29
|
+
|
30
|
+
h2. Installation
|
31
|
+
|
32
|
+
Get it in one of the following ways:
|
33
|
+
|
34
|
+
* RubyForge: http://stella.rubyforge.org/
|
35
|
+
** gem install stella
|
36
|
+
* git clone git://github.com/solutious/stella.git
|
37
|
+
** git submodule init
|
38
|
+
** git submodule update
|
39
|
+
|
40
|
+
Use ab, siege, and httperf like you normally would with the addition of stella at the beginning (examples are below).
|
41
|
+
|
42
|
+
h3. Debian (and derivatives)
|
43
|
+
|
44
|
+
Debian and its derivative (Ubunutu) handling packing a bit differently (see: http://pkg-ruby-extras.alioth.debian.org/rubygems.html). There are a couple errors to watch out for during the installation. The solutions are below:
|
45
|
+
|
46
|
+
"no such file to load -- mkmf (LoadError)"
|
47
|
+
$ apt-get install ruby1.8-dev
|
48
|
+
|
49
|
+
"ERROR: RDoc documentation generator not installed!"
|
50
|
+
$ apt-get install rdoc
|
51
|
+
|
52
|
+
|
53
|
+
h3. Installing libpcap and Ruby-Pcap
|
54
|
+
|
55
|
+
*Stella currently supports packet filtering with Native Ruby (no JRuby) on Linux/Unix/OS X only.*
|
56
|
+
*Ruby-Pcap does not compile with Ruby 1.9.1-RC1*
|
57
|
+
|
58
|
+
libpcap and Ruby-Pcap are used to by Stella's watch command to filter packets off the network. This allows you to view HTTP requests and response (including headers and content) without having to configure a proxy. Both need to be compiled and installed separately:
|
59
|
+
* "libpcap":http://www.tcpdump.org/release/
|
60
|
+
* "Ruby-Pcap":http://www.goto.info.waseda.ac.jp/~fukusima/ruby/pcap-e.html
|
61
|
+
|
62
|
+
On Ruby, 1.8.6, Ruby-Pcap produces the following warnings at runtime: "pcap.bundle: warning: do not use Fixnums as Symbols". See: support/ruby-pcap-takuma-notes.txt.
|
63
|
+
|
64
|
+
|
65
|
+
h2. Usage Examples
|
66
|
+
|
67
|
+
Run Apache Bench with a warmup and rampup from 10 to 20 virtual users in increments of 5
|
68
|
+
$ stella --warmup=0.5 --rampup=5,20 ab -c 10 -n 50 http://stellaaahhhh.com/search?term=trooper
|
69
|
+
|
70
|
+
Run Siege, repeat the test 5 times. Automatically creates a summary averages and standard deviations.
|
71
|
+
$ stella --agent=ff-3-osx --testruns=5 siege -c 10 -r 5 -b http://stellaaahhhh.com/search?term=flock+of+seagulls
|
72
|
+
|
73
|
+
Run Httperf like you normally would (but all the test data will be collected for you)
|
74
|
+
$ stella httperf --hog --client=0/1 --server=127.0.0.1 --port=5600 --uri=/ --rate=50 --num-conns=100 --timeout=5
|
75
|
+
|
76
|
+
Monitor DNS traffic using Pcap
|
77
|
+
$ stella watch -C dns
|
78
|
+
|
79
|
+
Monitor HTTP traffic using Pcap
|
80
|
+
$ stella watch -C http
|
81
|
+
|
82
|
+
Monitor HTTP traffic using a proxy (don't forget to configure your browser)
|
83
|
+
$ stella watch -P
|
84
|
+
|
85
|
+
|
86
|
+
h3. Sample Output
|
87
|
+
|
88
|
+
<pre><code>
|
89
|
+
$ stella -f csv -x 5 -w 0.75 -r 25,125 -m "httpd 2.2.9-prefork" siege -c 75 -r 10 -b http://testapp:5600/
|
90
|
+
Writing test data to: stella/testruns/2008-12-23/test-054
|
91
|
+
|
92
|
+
Warmup: 3750@37/1 100% 264.29/s 0.140s 0.024MB/s 0.340MB 14.000s .
|
93
|
+
|
94
|
+
-------------------------------------------------------------------
|
95
|
+
REQ@VU/s AVAIL REQ/s RTIME DATA/s DATA TIME
|
96
|
+
|
97
|
+
Run 01: 7500@75/1 100% 345.30/s 0.210s 0.032MB/s 0.690MB 21.720s
|
98
|
+
Run 02: 7500@75/1 100% 360.58/s 0.200s 0.033MB/s 0.690MB 20.800s
|
99
|
+
Run 03: 7500@75/1 100% 359.02/s 0.210s 0.033MB/s 0.690MB 20.890s
|
100
|
+
-------------------------------------------------------------------
|
101
|
+
Total: 22500@73 100% 354.97/s 0.207s 0.033MB/s 2.070MB 63.410s
|
102
|
+
Std Dev: 6.86/s 0.005s 0.001MB/s 0.414s
|
103
|
+
|
104
|
+
Run 04: 10000@100/1 100% 384.47/s 0.260s 0.035MB/s 0.920MB 26.010s
|
105
|
+
Run 05: 10000@100/1 100% 385.06/s 0.260s 0.035MB/s 0.920MB 25.970s
|
106
|
+
Run 06: 10000@100/1 100% 380.95/s 0.260s 0.035MB/s 0.920MB 26.250s
|
107
|
+
-------------------------------------------------------------------
|
108
|
+
Total: 30000@98 100% 383.49/s 0.260s 0.035MB/s 2.760MB 78.230s
|
109
|
+
Std Dev: 1.81/s 0.000s 0.000MB/s 0.124s
|
110
|
+
|
111
|
+
Run 07: 12500@125/1 100% 397.20/s 0.310s 0.036MB/s 1.140MB 31.470s
|
112
|
+
Run 08: 12500@125/1 100% 397.08/s 0.310s 0.036MB/s 1.140MB 31.480s
|
113
|
+
Run 09: 12500@125/1 100% 397.58/s 0.310s 0.036MB/s 1.140MB 31.440s
|
114
|
+
-------------------------------------------------------------------
|
115
|
+
Total: 37500@123 100% 397.29/s 0.310s 0.036MB/s 3.420MB 94.390s
|
116
|
+
Std Dev: 0.21/s 0.000s 0.000MB/s 0.017s
|
117
|
+
|
118
|
+
-------------------------------------------------------------------
|
119
|
+
Total: 90000@98 100% 378.58/s 0.259s 0.035MB/s 8.250MB 236.030s
|
120
|
+
Std Dev: 18.09/s 0.042s 0.002MB/s 4.225s
|
121
|
+
</pre></code>
|
122
|
+
|
123
|
+
All test data is collected under ./stella (this can be changed with the parameter --datapath):
|
124
|
+
|
125
|
+
$ ls -l ./stella/testruns/2008-12-23/
|
126
|
+
test-001 test-002 test-003 test-004 test-005 test-006 ... test-054
|
127
|
+
|
128
|
+
|
129
|
+
A symbolic link points to the most recent test:
|
130
|
+
|
131
|
+
$ ls -l ./stella/latest/
|
132
|
+
ID.txt MESSAGE.txt SUMMARY.csv run01 run02 run03 run04 run05 warmup
|
133
|
+
|
134
|
+
|
135
|
+
Each run directory contains all associated data, including the command and configuration
|
136
|
+
|
137
|
+
$ ls -l ./stella/latest/run01/
|
138
|
+
COMMAND.txt STDOUT.txt siege.log STDERR.txt SUMMARY.csv siegerc
|
139
|
+
|
140
|
+
|
141
|
+
h2. Known Issues
|
142
|
+
|
143
|
+
* The output for the REQ@VU/s columns is a work in progress. It's not aligned across tools and it will likely change in the next release.
|
144
|
+
* The summary data has not been audited. Don't trust and double verify!
|
145
|
+
* httperf is functional but not all parameters are supported.
|
146
|
+
* The Ruby API has not been finalized. It's functional but there's no example because it is subject to change.
|
147
|
+
* There is an issue with parsing ipv6 ip addresses with Ruby-Pcap or Net-DNS. This affects only dns sniffing with pcap. Reproduce by running "stella watch -C dns" and requesting "apple.com"
|
148
|
+
|
149
|
+
|
150
|
+
h2. Report an issue
|
151
|
+
|
152
|
+
Email issues and bugs to stella@solutious.com
|
153
|
+
|
154
|
+
|
155
|
+
h2. More Information
|
156
|
+
|
157
|
+
"Stellaaahhhh":http://www.youtube.com/watch?v=wmq-JDonTpc
|
158
|
+
|
159
|
+
|
160
|
+
h2. License
|
161
|
+
|
162
|
+
See LICENSE.txt
|
data/Rakefile
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'fileutils'
|
7
|
+
include FileUtils
|
8
|
+
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
# SPECS ===============================================================
|
12
|
+
|
13
|
+
desc 'Run specs with unit test style output'
|
14
|
+
task :test do |t|
|
15
|
+
# sh "specrb -s tests/*_test.rb"
|
16
|
+
sh "specrb -s tests/*_test.rb"
|
17
|
+
end
|
18
|
+
|
19
|
+
# PACKAGE =============================================================
|
20
|
+
|
21
|
+
|
22
|
+
STELLA_HOME = File.expand_path(File.join(File.dirname(__FILE__)))
|
23
|
+
$: << File.join(STELLA_HOME, 'lib')
|
24
|
+
|
25
|
+
require 'stella'
|
26
|
+
version = Stella::VERSION.to_s
|
27
|
+
name = "stella"
|
28
|
+
|
29
|
+
spec = Gem::Specification.new do |s|
|
30
|
+
s.name = name
|
31
|
+
s.version = version
|
32
|
+
s.summary = "Your friend in performance testing."
|
33
|
+
s.description = "Run Apache Bench, Siege, or httperf tests in batches and aggregate results."
|
34
|
+
s.author = "Delano Mandelbaum"
|
35
|
+
s.email = "delano@solutious.com"
|
36
|
+
s.homepage = "http://stella.solutious.com/"
|
37
|
+
s.executables = [ "stella", "stella.bat" ]
|
38
|
+
s.rubyforge_project = "stella"
|
39
|
+
s.extra_rdoc_files = ['README.textile']
|
40
|
+
|
41
|
+
# NOTE: how to make optional dependencies?
|
42
|
+
s.add_dependency 'mongrel'
|
43
|
+
s.add_dependency 'rspec'
|
44
|
+
s.add_dependency 'net-dns'
|
45
|
+
|
46
|
+
s.platform = Gem::Platform::RUBY
|
47
|
+
s.has_rdoc = true
|
48
|
+
|
49
|
+
s.files = %w(Rakefile) + Dir.glob("{bin,doc,lib,tests,support,vendor}/**/**/*")
|
50
|
+
|
51
|
+
s.require_path = "lib"
|
52
|
+
s.bindir = "bin"
|
53
|
+
end
|
54
|
+
|
55
|
+
Rake::GemPackageTask.new(spec) do |p|
|
56
|
+
p.need_tar = true if RUBY_PLATFORM !~ /mswin/
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
task :install => [ :rdoc, :package ] do
|
62
|
+
sh %{sudo gem install pkg/#{name}-#{version}.gem}
|
63
|
+
end
|
64
|
+
|
65
|
+
task :uninstall => [ :clean ] do
|
66
|
+
sh %{sudo gem uninstall #{name}}
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
Rake::RDocTask.new do |t|
|
72
|
+
t.rdoc_dir = 'doc'
|
73
|
+
t.title = "stella, a friend in performance testing"
|
74
|
+
t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
|
75
|
+
t.options << '--charset' << 'utf-8'
|
76
|
+
t.rdoc_files.include('LICENSE.txt')
|
77
|
+
t.rdoc_files.include('README.textile')
|
78
|
+
t.rdoc_files.include('CHANGES.txt')
|
79
|
+
t.rdoc_files.include('lib/utils/*.rb')
|
80
|
+
t.rdoc_files.include('lib/stella.rb')
|
81
|
+
t.rdoc_files.include('lib/stella/*.rb')
|
82
|
+
t.rdoc_files.include('lib/stella/**/*.rb')
|
83
|
+
end
|
84
|
+
|
85
|
+
CLEAN.include [ 'pkg', '*.gem', '.config', 'doc' ]
|
86
|
+
|
87
|
+
|
88
|
+
|
data/bin/stella
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
STELLA_HOME = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
4
|
+
$:.unshift(File.join(STELLA_HOME, 'lib')) # Make sure our local lib is first in line
|
5
|
+
|
6
|
+
require 'stella'
|
7
|
+
require 'stella/cli'
|
8
|
+
|
9
|
+
## Create and run the application
|
10
|
+
app = Stella::CLI.new(ARGV, STDIN)
|
11
|
+
app.run
|
12
|
+
|
data/bin/stella.bat
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
@echo off
|
2
|
+
|
3
|
+
rem Check for funkiness when called from another batch script.
|
4
|
+
rem We want FULL_PATH to contain the full path to the stella bin directory.
|
5
|
+
IF EXIST "%~dp0stella.bat" (set FULL_PATH=%~dp0) ELSE (set FULL_PATH=%~dp$PATH:0)
|
6
|
+
|
7
|
+
rem Check for JRuby, otherwise use Ruby.
|
8
|
+
rem We want EXECUTABLE to contain either "jruby" or "ruby"
|
9
|
+
IF EXIST "%JRUBY_HOME%" (set EXECUTABLE=jruby) ELSE (set EXECUTABLE=ruby)
|
10
|
+
|
11
|
+
rem Call the Ruby script, passing it all the arguments.
|
12
|
+
@%EXECUTABLE% %FULL_PATH%stella %*
|
data/lib/daemonize.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Daemonize
|
2
|
+
VERSION = "0.1.2"
|
3
|
+
|
4
|
+
# Try to fork if at all possible retrying every 5 sec if the
|
5
|
+
# maximum process limit for the system has been reached
|
6
|
+
def safefork
|
7
|
+
tryagain = true
|
8
|
+
|
9
|
+
while tryagain
|
10
|
+
tryagain = false
|
11
|
+
begin
|
12
|
+
if pid = fork
|
13
|
+
return pid
|
14
|
+
end
|
15
|
+
rescue Errno::EWOULDBLOCK
|
16
|
+
sleep 5
|
17
|
+
tryagain = true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# This method causes the current running process to become a daemon
|
23
|
+
# If closefd is true, all existing file descriptors are closed
|
24
|
+
def daemonize(oldmode=0, closefd=false)
|
25
|
+
srand # Split rand streams between spawning and daemonized process
|
26
|
+
safefork and exit # Fork and exit from the parent
|
27
|
+
|
28
|
+
# Detach from the controlling terminal
|
29
|
+
unless sess_id = Process.setsid
|
30
|
+
raise 'Cannot detach from controlled terminal'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Prevent the possibility of acquiring a controlling terminal
|
34
|
+
if oldmode.zero?
|
35
|
+
trap 'SIGHUP', 'IGNORE'
|
36
|
+
exit if pid = safefork
|
37
|
+
end
|
38
|
+
|
39
|
+
Dir.chdir "/" # Release old working directory
|
40
|
+
File.umask 0000 # Insure sensible umask
|
41
|
+
|
42
|
+
if closefd
|
43
|
+
# Make sure all file descriptors are closed
|
44
|
+
ObjectSpace.each_object(IO) do |io|
|
45
|
+
unless [STDIN, STDOUT, STDERR].include?(io)
|
46
|
+
io.close rescue nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
STDIN.reopen "/dev/null" # Free file descriptors and
|
52
|
+
STDOUT.reopen "/dev/null", "a" # point them somewhere sensible
|
53
|
+
STDERR.reopen STDOUT # STDOUT/STDERR should go to a logfile
|
54
|
+
return oldmode ? sess_id : 0 # Return value is mostly irrelevant
|
55
|
+
end
|
56
|
+
end
|
data/lib/pcaplet.rb
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'pcap'
|
2
|
+
|
3
|
+
|
4
|
+
# Pcaplet
|
5
|
+
#
|
6
|
+
# Adapted from Ruby portion of Ruby-Pcap:
|
7
|
+
# http://www.goto.info.waseda.ac.jp/~fukusima/ruby/pcap-e.html
|
8
|
+
# The lib/pcaplet.rb and lib/pcap_misc.rb files are in merge into this file
|
9
|
+
# and cleaned up. The Ruby-Pcap C extension was modified to apply several fixes
|
10
|
+
# so it would compile on OS X and to remove several warning messages. With
|
11
|
+
# help from: http://d.hatena.ne.jp/takuma104/20080210/1202638583
|
12
|
+
# We specifically removed the dependency on ARGV and OptParse. It was messy
|
13
|
+
# and required ARGV to be specifically modified before requiring this package.
|
14
|
+
# Manual: http://www.goto.info.waseda.ac.jp/~fukusima/ruby/pcap/doc/index.html
|
15
|
+
class Pcaplet
|
16
|
+
|
17
|
+
attr_accessor :debug, :verbose
|
18
|
+
# do not convert address to name
|
19
|
+
attr_accessor :convert
|
20
|
+
attr_accessor :device, :rfile, :count, :snaplen, :filter
|
21
|
+
|
22
|
+
def initialize(args = {})
|
23
|
+
|
24
|
+
@debug = args[:debug] || false
|
25
|
+
@verbose = args[:verbose] || false
|
26
|
+
@device = args[:device] || guess_device
|
27
|
+
@rfile = args[:rfile]
|
28
|
+
@convert = args[:convert] || false
|
29
|
+
@count = args[:count].to_i || 1000
|
30
|
+
@snaplen = args[:snaplen].to_i > 0 ? args[:snaplen] : 1500
|
31
|
+
@filter = args[:filter] || ''
|
32
|
+
|
33
|
+
Pcap.convert = @convert
|
34
|
+
|
35
|
+
# check option consistency
|
36
|
+
usage(1) if @device && @rfile
|
37
|
+
if !@device and !@rfile
|
38
|
+
@device = Pcap.lookupdev
|
39
|
+
end
|
40
|
+
|
41
|
+
# open
|
42
|
+
begin
|
43
|
+
if @device
|
44
|
+
@capture = Pcap::Capture.open_live(@device, @snaplen)
|
45
|
+
elsif @rfile
|
46
|
+
if @rfile !~ /\.gz$/
|
47
|
+
@capture = Capture.open_offline(@rfile)
|
48
|
+
else
|
49
|
+
$stdin = IO.popen("gzip -dc < #@rfile", 'r')
|
50
|
+
@capture = Capture.open_offline('-')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@capture.setfilter(@filter) if @filter
|
54
|
+
rescue Pcap::PcapError, ArgumentError
|
55
|
+
$stdout.flush
|
56
|
+
$stderr.puts $!
|
57
|
+
exit(1)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
attr('capture')
|
62
|
+
|
63
|
+
|
64
|
+
def add_filter(f)
|
65
|
+
if @filter == nil || @filter =~ /^\s*$/ # if empty
|
66
|
+
#puts "filter is nil or empty"
|
67
|
+
@filter = f
|
68
|
+
else
|
69
|
+
#puts "filter is #{@filter}"
|
70
|
+
f = f.source if f.is_a? Filter
|
71
|
+
@filter = "( #{@filter} ) and ( #{f} )"
|
72
|
+
end
|
73
|
+
#puts "filter being set #{@filter}"
|
74
|
+
@capture.setfilter(@filter)
|
75
|
+
end
|
76
|
+
|
77
|
+
def each_packet(&block)
|
78
|
+
|
79
|
+
begin
|
80
|
+
duplicated = (RUBY_PLATFORM =~ /linux/ && @device == "lo")
|
81
|
+
unless duplicated
|
82
|
+
@capture.loop(@count, &block)
|
83
|
+
else
|
84
|
+
flip = true
|
85
|
+
@capture.loop(@count) do |pkt|
|
86
|
+
flip = (! flip)
|
87
|
+
next if flip
|
88
|
+
block.call pkt
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
alias each each_packet
|
95
|
+
|
96
|
+
def close
|
97
|
+
@capture.close
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
module Pcap
|
104
|
+
class Packet
|
105
|
+
def to_s
|
106
|
+
'Some packet'
|
107
|
+
end
|
108
|
+
|
109
|
+
def inspect
|
110
|
+
"#<#{type}: #{self}>"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class IPPacket
|
115
|
+
def to_s
|
116
|
+
"#{ip_src} > #{ip_dst}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class TCPPacket
|
121
|
+
def tcp_data_len
|
122
|
+
ip_len - 4 * (ip_hlen + tcp_hlen)
|
123
|
+
end
|
124
|
+
|
125
|
+
# The 3-way handshake that initiates a request
|
126
|
+
# ....S. --->
|
127
|
+
# .A..S. <---
|
128
|
+
# .A.... --->
|
129
|
+
#
|
130
|
+
# The teardown procedure at the end of the request
|
131
|
+
# .A...F --->
|
132
|
+
# .A.... <---
|
133
|
+
# .A...F --->
|
134
|
+
# .A.... <...
|
135
|
+
def tcp_flags_s
|
136
|
+
return \
|
137
|
+
(tcp_urg? ? 'U' : '.') + # Urgent
|
138
|
+
(tcp_ack? ? 'A' : '.') + # ACKnowledgement: Successful transfer
|
139
|
+
(tcp_psh? ? 'P' : '.') + # Push
|
140
|
+
(tcp_rst? ? 'R' : '.') + # Reset
|
141
|
+
(tcp_syn? ? 'S' : '.') + # SYNchronization: this is the first segment in a new transaction
|
142
|
+
(tcp_fin? ? 'F' : '.') # FINal: final transaction
|
143
|
+
end
|
144
|
+
|
145
|
+
def to_s
|
146
|
+
"#{src}:#{sport} > #{dst}:#{dport} #{tcp_flags_s}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class UDPPacket
|
151
|
+
def to_s
|
152
|
+
"#{src}:#{sport} > #{dst}:#{dport} len #{udp_len} sum #{udp_sum}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class ICMPPacket
|
157
|
+
def to_s
|
158
|
+
"#{src} > #{dst}: icmp: #{icmp_typestr}"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Backword compatibility
|
164
|
+
#
|
165
|
+
IpPacket = IPPacket unless defined? IpPacket
|
166
|
+
IpAddress = IPAddress unless defined? IpAddress
|
167
|
+
TcpPacket = TCPPacket unless defined? TcpPacket
|
168
|
+
UdpPacket = UDPPacket unless defined? UdpPacket
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
class Time
|
173
|
+
# tcpdump style format
|
174
|
+
def tcpdump
|
175
|
+
sprintf "%0.2d:%0.2d:%0.2d.%0.6d", hour, min, sec, tv_usec
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
|