DIY-pcap 0.0.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/pcap +62 -5
- data/bin/rpcap +62 -6
- data/lib/diy/builder.rb +14 -16
- data/lib/diy/controller.rb +50 -33
- data/lib/diy/device_finder.rb +26 -0
- data/lib/diy/dig.rb +7 -6
- data/lib/diy/logger.rb +7 -0
- data/lib/diy/offline.rb +98 -28
- data/lib/diy/packet.rb +17 -0
- data/lib/diy/pcap.rb +40 -17
- data/lib/diy/strategy_builder.rb +5 -12
- data/lib/diy/utils.rb +12 -0
- data/lib/diy/version.rb +5 -5
- data/lib/diy/worker.rb +49 -0
- data/lib/diy/worker_keeper.rb +25 -0
- data/simple/4000port.rb +20 -0
- data/simple/4000port/r1.dat +0 -0
- data/simple/4000port/r3.dat +0 -0
- data/simple/4000port/r4.dat +0 -0
- data/simple/4000port/r6.dat +0 -0
- data/simple/4000port/r7.dat +0 -0
- data/simple/4000port/s1.dat +0 -0
- data/simple/4000port/s2.dat +0 -0
- data/simple/4000port/s3.dat +0 -0
- data/simple/4000port/s4.dat +0 -0
- data/simple/4000port/s5.dat +0 -0
- data/simple/4000port/s6.dat +0 -0
- data/simple/4000port/s8.dat +0 -0
- data/simple/howto.vsd +0 -0
- data/spec/controller_spec.rb +36 -0
- data/spec/device_finder_spec.rb +16 -0
- data/spec/offline_spec.rb +26 -29
- data/spec/worker_spec.rb +58 -0
- metadata +24 -9
- data/lib/diy/queue.rb +0 -174
- data/lib/diy/recver.rb +0 -33
- data/lib/diy/sender.rb +0 -26
- data/spec/builder_spec.rb +0 -82
- data/spec/queue_spec.rb +0 -84
- data/spec/sender_spec.rb +0 -21
data/lib/diy/packet.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module DIY
|
2
|
+
class Packet
|
3
|
+
def initialize( content, detail_msg = nil )
|
4
|
+
@content = content
|
5
|
+
@detail_msg = detail_msg
|
6
|
+
end
|
7
|
+
attr_reader :content, :detail_msg
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
@content
|
11
|
+
end
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
"#{Utils.pp(@content)} : from #{@detail_msg}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/diy/pcap.rb
CHANGED
@@ -17,15 +17,20 @@ module DIY
|
|
17
17
|
attr_accessor :timeout, :dir, :device_name
|
18
18
|
|
19
19
|
def send(pkt_dir)
|
20
|
-
@pkt_stack <<
|
20
|
+
@pkt_stack << PacketEx.new( pkt_dir2pkt(pkt_dir), PacketEx::SEND, pkt_dir)
|
21
21
|
end
|
22
22
|
|
23
23
|
def recv(pkt_dir)
|
24
|
-
@pkt_stack <<
|
24
|
+
@pkt_stack << PacketEx.new( pkt_dir2pkt(pkt_dir), PacketEx::RECV, pkt_dir)
|
25
25
|
end
|
26
26
|
|
27
27
|
def pkt_dir2pkt(dir)
|
28
|
-
File.read( File.join( @dir, dir ) )
|
28
|
+
#~ File.read( File.join( @dir, dir ) )
|
29
|
+
ret = ""
|
30
|
+
File.open( File.join( @dir, dir), "rb") do |f|
|
31
|
+
ret += f.read(65535) until f.eof?
|
32
|
+
end
|
33
|
+
ret
|
29
34
|
end
|
30
35
|
|
31
36
|
def run
|
@@ -44,9 +49,9 @@ module DIY
|
|
44
49
|
def run_client
|
45
50
|
@pkt_stack.each do |pkt|
|
46
51
|
if pkt.to_outer?
|
47
|
-
send_pkt(pkt
|
52
|
+
send_pkt(pkt)
|
48
53
|
else
|
49
|
-
recv_pkt(pkt
|
54
|
+
recv_pkt(pkt)
|
50
55
|
end
|
51
56
|
end
|
52
57
|
end
|
@@ -54,33 +59,46 @@ module DIY
|
|
54
59
|
def run_server
|
55
60
|
@pkt_stack.each do |pkt|
|
56
61
|
if pkt.to_inner?
|
57
|
-
send_pkt(pkt
|
62
|
+
send_pkt(pkt)
|
58
63
|
else
|
59
|
-
recv_pkt(pkt
|
64
|
+
recv_pkt(pkt)
|
60
65
|
end
|
61
66
|
end
|
62
67
|
end
|
63
68
|
|
64
69
|
def send_pkt(pkt)
|
65
70
|
sleep 1
|
66
|
-
logger.info("send pkt: [ #{Time.now} ]#{pkt[0..10].dump}...")
|
67
|
-
|
71
|
+
logger.info("send pkt: [ #{Time.now} ]#{pkt.pkt[0..10].dump}(file: #{pkt.filename}, size: #{pkt.size})...")
|
72
|
+
pkt = pkt.pkt
|
73
|
+
pkt = fill60(pkt)
|
74
|
+
@driver.send_packet(pkt)
|
68
75
|
end
|
69
76
|
|
70
77
|
def recv_pkt(pkt)
|
71
|
-
logger.info("I hope pkt: #{pkt[0..10].dump}")
|
78
|
+
logger.info("I hope pkt: #{pkt.pkt[0..10].dump}(file: #{pkt.filename}, size: #{pkt.size})...")
|
79
|
+
pkt = pkt.pkt
|
80
|
+
pkt = fill60(pkt)
|
72
81
|
@driver.loop do |this, new_pkt|
|
73
82
|
#~ logger.info("recv pkt: [ #{new_pkt.time} ]: #{new_pkt.body[0..10].dump}..." )
|
74
|
-
|
75
|
-
|
76
|
-
logger.info
|
83
|
+
new_pkt_body = fill60(new_pkt.body)
|
84
|
+
if new_pkt_body == pkt
|
85
|
+
logger.info("recv pkt: [ #{new_pkt.time} ]: #{new_pkt_body[0..10].dump}..." )
|
86
|
+
logger.info "got the same pkt,next"
|
77
87
|
return true
|
78
88
|
end
|
79
89
|
end
|
80
90
|
end
|
81
91
|
|
92
|
+
def fill60(pkt)
|
93
|
+
if pkt.size < 60
|
94
|
+
logger.debug "pkt size #{pkt.size} less than 60, fill with zero"
|
95
|
+
pkt += "0" * (60 - pkt.size)
|
96
|
+
end
|
97
|
+
pkt
|
98
|
+
end
|
99
|
+
|
82
100
|
def logger
|
83
|
-
@@logger ||= Logger
|
101
|
+
@@logger ||= DIY::Logger
|
84
102
|
end
|
85
103
|
|
86
104
|
def logger=(logger)
|
@@ -89,12 +107,13 @@ module DIY
|
|
89
107
|
|
90
108
|
end
|
91
109
|
|
92
|
-
class
|
110
|
+
class PacketEx
|
93
111
|
SEND = 1
|
94
112
|
RECV = 0
|
95
|
-
def initialize( pkt, pos )
|
113
|
+
def initialize( pkt, pos, filename = nil )
|
96
114
|
@pkt = pkt
|
97
115
|
@pos = pos
|
116
|
+
@filename = filename
|
98
117
|
end
|
99
118
|
|
100
119
|
def to_outer?
|
@@ -105,6 +124,10 @@ module DIY
|
|
105
124
|
@pos == RECV
|
106
125
|
end
|
107
126
|
|
108
|
-
|
127
|
+
def size
|
128
|
+
@pkt.size
|
129
|
+
end
|
130
|
+
|
131
|
+
attr_reader :pkt, :pos, :filename
|
109
132
|
end
|
110
133
|
end
|
data/lib/diy/strategy_builder.rb
CHANGED
@@ -2,10 +2,9 @@
|
|
2
2
|
require 'logger'
|
3
3
|
module DIY
|
4
4
|
class StrategyBuilder
|
5
|
-
def initialize
|
5
|
+
def initialize
|
6
6
|
@ins = []
|
7
7
|
@logger = DIY::Logger
|
8
|
-
@queue = queue
|
9
8
|
end
|
10
9
|
attr_reader :queue
|
11
10
|
|
@@ -22,27 +21,21 @@ module DIY
|
|
22
21
|
@logger
|
23
22
|
end
|
24
23
|
|
25
|
-
def recv_pkt
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def recv_pkt_queue(queue, recv_pkt)
|
30
|
-
hope_pkt = queue.peek
|
31
|
-
logger.debug("recv_pkt, I hope: #{ hope_pkt[0..10].dump rescue nil }...")
|
24
|
+
def call(hope_pkt, recv_pkt, queue)
|
25
|
+
logger.debug("recv_pkt, I hope: #{ Utils.pp(hope_pkt) rescue nil }...")
|
32
26
|
|
33
27
|
return if hope_pkt.nil?
|
34
28
|
|
35
29
|
@ins.each do |strategy|
|
36
30
|
begin
|
37
|
-
|
31
|
+
ret = strategy.call(hope_pkt.content, recv_pkt.content, queue)
|
38
32
|
rescue Exception => e
|
39
33
|
logger.error("user strategy exception: #{e.class} -> #{e.message}")
|
40
34
|
raise
|
41
|
-
#TODO 也许仅仅忽略?
|
42
35
|
else
|
43
36
|
if ret == Strategy::OK
|
44
37
|
logger.info("pkt same:")
|
45
|
-
queue.
|
38
|
+
queue.shift
|
46
39
|
return
|
47
40
|
elsif ret == Strategy::OK_NO_POP
|
48
41
|
logger.info("pkt skip:")
|
data/lib/diy/utils.rb
CHANGED
@@ -3,17 +3,29 @@ module DIY
|
|
3
3
|
class << self
|
4
4
|
# 漂亮输出包的前十个内容
|
5
5
|
def pp(pkt)
|
6
|
+
pkt = pkt.content if pkt.kind_of?(DIY::Packet)
|
6
7
|
return nil if pkt.nil?
|
7
8
|
( pkt[0..10] + "..." ).dump
|
8
9
|
end
|
9
10
|
|
10
11
|
def src_mac(pkt)
|
12
|
+
pkt = pkt.content if pkt.kind_of?(DIY::Packet)
|
11
13
|
pkt[6..11]
|
12
14
|
end
|
13
15
|
|
14
16
|
def dst_mac(pkt)
|
17
|
+
pkt = pkt.content if pkt.kind_of?(DIY::Packet)
|
15
18
|
pkt[0..5]
|
16
19
|
end
|
20
|
+
|
21
|
+
def wait_until( timeout = 20, &block )
|
22
|
+
timeout(timeout) do
|
23
|
+
loop do
|
24
|
+
break if block.call
|
25
|
+
sleep 0.01
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
17
29
|
end
|
18
30
|
end
|
19
31
|
end
|
data/lib/diy/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
module DIY
|
2
|
-
class PCAP
|
3
|
-
VERSION = "0.0
|
4
|
-
end
|
5
|
-
end
|
1
|
+
module DIY
|
2
|
+
class PCAP
|
3
|
+
VERSION = "0.2.0"
|
4
|
+
end
|
5
|
+
end
|
data/lib/diy/worker.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding : utf-8
|
2
|
+
require 'diy/packet'
|
3
|
+
require 'drb'
|
4
|
+
module DIY
|
5
|
+
include DRbUndumped
|
6
|
+
class Worker
|
7
|
+
def initialize(live)
|
8
|
+
@live = live
|
9
|
+
@recv_t = nil
|
10
|
+
@start = false
|
11
|
+
loop_recv
|
12
|
+
end
|
13
|
+
|
14
|
+
# 发包
|
15
|
+
def inject(pkts)
|
16
|
+
pkts.each do |pkt|
|
17
|
+
DIY::Logger.info "send pkt: #{pkt.inspect}"
|
18
|
+
@live.send_packet(pkt.content)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def loop_recv
|
23
|
+
@recv_t = Thread.new do
|
24
|
+
DIY::Logger.info "start thread recving pkt..."
|
25
|
+
@live.loop do |this, pkt|
|
26
|
+
next unless @start
|
27
|
+
@block.call(pkt.body) if @block
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#收包
|
33
|
+
def ready(&block)
|
34
|
+
DIY::Logger.info("start recv pkt")
|
35
|
+
@block = block
|
36
|
+
@start = true
|
37
|
+
end
|
38
|
+
|
39
|
+
def terminal
|
40
|
+
DIY::Logger.info("stop recv pkt")
|
41
|
+
@start = false
|
42
|
+
end
|
43
|
+
|
44
|
+
def inspect
|
45
|
+
"<Worker: #{@live.net}>"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding : utf-8
|
2
|
+
require 'drb'
|
3
|
+
require 'diy/worker'
|
4
|
+
|
5
|
+
module DIY
|
6
|
+
# 创建DRb服务
|
7
|
+
class WorkerKeeper
|
8
|
+
def initialize(worker, uri)
|
9
|
+
@worker = worker
|
10
|
+
@uri = uri
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
DIY::Logger.info "serving at #{@uri}"
|
15
|
+
DRb.start_service(@uri, @worker)
|
16
|
+
running = true
|
17
|
+
trap("INT") { running = false }
|
18
|
+
while running
|
19
|
+
sleep 0.5
|
20
|
+
end
|
21
|
+
DIY::Logger.info "bye..."
|
22
|
+
DRb.stop_service
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/simple/4000port.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join( File.dirname(__FILE__), '..', 'lib' )
|
2
|
+
require 'rubygems'
|
3
|
+
require 'diy/pcap'
|
4
|
+
|
5
|
+
# client and server
|
6
|
+
DIY::PCAP.new do |s|
|
7
|
+
s.dir = File.join( File.dirname(__FILE__), '4000port')
|
8
|
+
s.send("s1.dat")
|
9
|
+
s.recv("r1.dat")
|
10
|
+
s.send("s2.dat")
|
11
|
+
s.send("s3.dat")
|
12
|
+
s.recv("r3.dat")
|
13
|
+
s.send("s4.dat")
|
14
|
+
s.recv("r4.dat")
|
15
|
+
s.send("s5.dat")
|
16
|
+
s.send("s6.dat")
|
17
|
+
s.recv("r6.dat")
|
18
|
+
s.recv("r7.dat")
|
19
|
+
s.send("s8.dat")
|
20
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/simple/howto.vsd
ADDED
Binary file
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DIY::Builder do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@device_name = FFI::PCap.dump_devices[0][0]
|
7
|
+
DIY::Logger.info( "Initialize Live: #{@device_name}" )
|
8
|
+
@live = FFI::PCap::Live.new(:dev=>@device_name, :handler => FFI::PCap::Handler, :promisc => true)
|
9
|
+
@live2 = FFI::PCap::Live.new(:dev=>@device_name, :handler => FFI::PCap::Handler, :promisc => true)
|
10
|
+
|
11
|
+
@curi = "druby://localhost:7878"
|
12
|
+
@suri = "druby://localhost:7879"
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
it "#run" do
|
17
|
+
# client create
|
18
|
+
Thread.abort_on_exception = true
|
19
|
+
client_t = Thread.new do
|
20
|
+
client = DIY::Worker.new(@live)
|
21
|
+
DIY::WorkerKeeper.new(client, @curi).run
|
22
|
+
end
|
23
|
+
|
24
|
+
server_t = Thread.new do
|
25
|
+
server = DIY::Worker.new(@live2)
|
26
|
+
DIY::WorkerKeeper.new(server, @suri).run
|
27
|
+
end
|
28
|
+
|
29
|
+
sleep 1
|
30
|
+
builder = DIY::Builder.new do
|
31
|
+
pcapfiles "helper/http.pcap"
|
32
|
+
use DIY::SimpleStrategy.new
|
33
|
+
end
|
34
|
+
builder.run
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'diy/device_finder'
|
3
|
+
|
4
|
+
describe DIY::DeviceFinder do
|
5
|
+
it "#devices" do
|
6
|
+
DIY::DeviceFinder.devices
|
7
|
+
end
|
8
|
+
|
9
|
+
it "#pp_devices" do
|
10
|
+
DIY::DeviceFinder.pp_devices
|
11
|
+
end
|
12
|
+
|
13
|
+
it "#smart_select" do
|
14
|
+
DIY::DeviceFinder.smart_select.should be_kind_of(String)
|
15
|
+
end
|
16
|
+
end
|
data/spec/offline_spec.rb
CHANGED
@@ -1,47 +1,44 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe DIY::Offline do
|
4
|
-
it "should get single pkt" do
|
5
|
-
file = "helper/gre.pcap"
|
6
|
-
offline = DIY::Offline.new(file)
|
7
|
-
offline.next.body.should == File.read( File.join( File.dirname(__FILE__), 'helper/pkt1' ) )
|
8
|
-
end
|
9
4
|
|
10
|
-
it "should get
|
11
|
-
|
12
|
-
offline = DIY::Offline.new(
|
13
|
-
|
5
|
+
it "should get next pcap" do
|
6
|
+
files = [ "helper/gre.pcap", "helper/app.pcap" ]
|
7
|
+
offline = DIY::Offline.new(files)
|
8
|
+
offline.next_pcap
|
9
|
+
lambda { offline.next_pcap }.should raise_error(DIY::EOFError)
|
14
10
|
end
|
15
11
|
|
16
|
-
it "should get
|
17
|
-
files = [ "helper/
|
12
|
+
it "should get next special first_pkt" do
|
13
|
+
files = [ "helper/app.pcap", "helper/gre.pcap" ]
|
18
14
|
offline = DIY::Offline.new(files)
|
19
|
-
|
15
|
+
22.times { offline.nexts }
|
16
|
+
offline.nexts.size.should == 1
|
20
17
|
end
|
21
18
|
|
22
|
-
it "should get
|
19
|
+
it "should get nexts two" do
|
23
20
|
files = [ "helper/gre.pcap", "helper/app.pcap" ]
|
24
21
|
offline = DIY::Offline.new(files)
|
22
|
+
offline.nexts.size.should == 1
|
23
|
+
offline.nexts.size.should == 2
|
24
|
+
offline.nexts.size.should == 2
|
25
25
|
offline.next_pcap
|
26
|
-
|
26
|
+
offline.nexts.size.should == 1
|
27
|
+
offline.nexts.size.should == 7
|
28
|
+
lambda { loop do offline.nexts end }.should raise_error(DIY::EOFError)
|
27
29
|
end
|
28
30
|
|
29
|
-
it "should get
|
30
|
-
files = [ "helper/
|
31
|
+
it "should get another two" do
|
32
|
+
files = [ "helper/http.pcap", "helper/gre.pcap" ]
|
31
33
|
offline = DIY::Offline.new(files)
|
32
|
-
offline.
|
33
|
-
offline.should
|
34
|
-
offline.
|
35
|
-
|
36
|
-
offline.
|
37
|
-
offline.
|
38
|
-
offline.
|
39
|
-
offline.
|
40
|
-
offline.fullname.should == "pkt: `helper/app.pcap: 1th' "
|
41
|
-
offline.should be_first_pkt
|
42
|
-
offline.next
|
43
|
-
offline.should_not be_first_pkt
|
44
|
-
offline.fullname.should == "pkt: `helper/app.pcap: 2th' "
|
34
|
+
offline.nexts.size.should == 1
|
35
|
+
offline.nexts.size.should == 1
|
36
|
+
offline.nexts.size.should == 1
|
37
|
+
#change to next
|
38
|
+
offline.nexts.size.should == 1
|
39
|
+
offline.nexts.size.should == 2
|
40
|
+
offline.nexts.size.should == 2
|
41
|
+
lambda { loop do offline.nexts end }.should raise_error(DIY::EOFError)
|
45
42
|
end
|
46
43
|
|
47
44
|
end
|