File Coverage

blib/lib/Metabrik/File/Pcap.pm
Criterion Covered Total %
statement 9 80 11.2
branch 0 46 0.0
condition 0 27 0.0
subroutine 3 10 30.0
pod 1 7 14.2
total 13 170 7.6


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # file::pcap Brik
5             #
6             package Metabrik::File::Pcap;
7 1     1   796 use strict;
  1         3  
  1         28  
8 1     1   4 use warnings;
  1         2  
  1         30  
9              
10 1     1   5 use base qw(Metabrik::Network::Frame);
  1         2  
  1         546  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable frame packet) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             input => [ qw(input) ],
20             output => [ qw(output) ],
21             eof => [ qw(0|1) ],
22             count => [ qw(count) ],
23             filter => [ qw(filter) ],
24             mode => [ qw(read|write) ],
25             first_layer => [ qw(layer) ],
26             _dump => [ qw(INTERNAL) ],
27             },
28             attributes_default => {
29             eof => 0,
30             filter => '',
31             mode => 'read',
32             first_layer => 'ETH',
33             },
34             commands => {
35             open => [ qw(input mode|OPTIONAL filter|first_layer|OPTIONAL) ],
36             close => [ ],
37             read => [ ],
38             read_next => [ qw(count|OPTIONAL) ],
39             is_eof => [ ],
40             from_read => [ qw(frame|$frame_list) ], # Inherited from N:F
41             to_read => [ qw(simple|$simple_list) ], # Inherited from N:F
42             write => [ qw(frame|$frame_list) ],
43             },
44             require_modules => {
45             'Net::Frame::Dump::Offline' => [ ],
46             'Net::Frame::Dump::Writer' => [ ],
47             },
48             };
49             }
50              
51             sub open {
52 0     0 0   my $self = shift;
53 0           my ($file, $mode, $arg3) = @_;
54              
55 0 0         if ($self->_dump) {
56 0           return $self->log->error("open: already opened");
57             }
58              
59 0   0       $mode ||= $self->mode;
60 0 0         $self->brik_help_run_undef_arg('open', $mode) or return;
61              
62 0           my $dump;
63 0 0         if ($mode eq 'read') {
    0          
64 0   0       $file ||= $self->input;
65 0 0         $self->brik_help_run_undef_arg('open', $file) or return;
66 0 0         $self->brik_help_run_file_not_found('open', $file) or return;
67              
68 0   0       my $filter = $arg3 || $self->filter || '';
69 0           $dump = Net::Frame::Dump::Offline->new(
70             file => $file,
71             filter => $filter,
72             keepTimestamp => 1,
73             );
74 0 0         $dump->start or return $self->log->error("open: offline start failed");
75             }
76             elsif ($mode eq 'write') {
77 0   0       $file ||= $self->output;
78 0 0         $self->brik_help_run_undef_arg('open', $file) or return;
79              
80 0   0       my $first_layer = $arg3 || $self->first_layer || 'ETH';
81 0           $dump = Net::Frame::Dump::Writer->new(
82             file => $file,
83             firstLayer => $first_layer,
84             );
85              
86 0 0         $dump->start or return $self->log->error("open: writer start failed");
87             }
88             else {
89 0           return $self->log->error("open: mode must be either read or write");
90             }
91              
92 0           return $self->_dump($dump);
93             }
94              
95             sub close {
96 0     0 0   my $self = shift;
97              
98 0           my $dump = $self->_dump;
99 0 0         if (defined($dump)) {
100 0           $dump->stop;
101 0           $self->eof(0);
102 0           $self->_dump(undef);
103             }
104              
105 0           return 1;
106             }
107              
108             # Will read everything until the end-of-file
109             sub read {
110 0     0 0   my $self = shift;
111              
112 0 0         if ($self->is_eof) {
113 0           return $self->log->error("read: end-of-file already reached");
114             }
115              
116 0           my $dump = $self->_dump;
117 0 0         $self->brik_help_run_undef_arg('open', $dump) or return;
118              
119 0           my @h = ();
120 0           while (my $h = $dump->next) {
121 0           push @h, $h;
122             }
123              
124 0           $self->eof(1);
125              
126 0           return \@h;
127             }
128              
129             sub read_next {
130 0     0 0   my $self = shift;
131 0           my ($count) = @_;
132              
133 0   0       $count ||= 1;
134 0           my $dump = $self->_dump;
135 0 0         $self->brik_help_run_undef_arg('open', $dump) or return;
136              
137 0           my @next = ();
138 0           my $read_count = 0;
139 0           while (my $h = $dump->next) {
140 0           push @next, $h;
141 0 0         last if ++$read_count == $count;
142             }
143              
144 0           return \@next;
145             }
146              
147             sub is_eof {
148 0     0 0   my $self = shift;
149              
150 0           return $self->eof;
151             }
152              
153             sub write {
154 0     0 0   my $self = shift;
155 0           my ($frames) = @_;
156              
157 0           my $dump = $self->_dump;
158 0 0         $self->brik_help_run_undef_arg('open', $dump) or return;
159 0 0         $self->brik_help_run_undef_arg('write', $frames) or return;
160 0 0         my $ref = $self->brik_help_run_invalid_arg('write', $frames, 'ARRAY', 'HASH')
161             or return;
162              
163 0 0         my $first = $ref eq 'ARRAY' ? $frames->[0] : $frames;
164 0 0         if ($ref eq 'ARRAY') {
165 0 0         if (@$frames <= 0) {
166 0           return $self->log->error("write: frames ARRAYREF is empty");
167             }
168 0 0 0       if (! exists($first->{raw})
      0        
169             || ! exists($first->{timestamp})
170             || ! exists($first->{firstLayer})) {
171 0           return $self->log->error("write: frames ARRAYREF does not contain a valid frame");
172             }
173             }
174             else { # Must be HASH because of previous checks
175 0 0 0       if (! exists($first->{raw})
      0        
176             || ! exists($first->{timestamp})
177             || ! exists($first->{firstLayer})) {
178 0           return $self->log->error("write: frames HASHREF does not contain a valid frame");
179             }
180             }
181              
182 0 0         if ($ref eq 'ARRAY') {
183 0           for my $simple (@$frames) {
184 0           $dump->write($simple);
185             }
186             }
187             else {
188 0           $dump->write($frames);
189             }
190              
191 0           return 1;
192             }
193              
194             1;
195              
196             __END__