File Coverage

blib/lib/POE/Filter/PPPHDLC.pm
Criterion Covered Total %
statement 44 44 100.0
branch 9 12 75.0
condition 2 6 33.3
subroutine 9 9 100.0
pod 0 4 0.0
total 64 75 85.3


line stmt bran cond sub pod time code
1             package POE::Filter::PPPHDLC;
2              
3 3     3   36446 use 5.006001;
  3         16  
  3         205  
4 3     3   19 use strict;
  3         6  
  3         112  
5 3     3   16 use warnings;
  3         10  
  3         5726  
6              
7             our $VERSION = '0.01';
8              
9             sub DEBUG () { 0 }
10              
11             sub HDLC_BUFFER () { 0 }
12              
13             sub new {
14 2     2 0 54 my $class = shift;
15 2         16 return bless [''], $class;
16             }
17              
18             # only arg is an array ref of chunks
19             sub get_one_start {
20 2     2 0 15 my $self = shift;
21             # stick the chunks onto the buffer
22 2         8 $self->[HDLC_BUFFER] .= join '', @{$_[0]};
  2         11  
23             }
24              
25             sub get_pending {
26 2     2 0 401 my $self = shift;
27 2 100       16 return [ $self->[HDLC_BUFFER] ] if length $self->[HDLC_BUFFER];
28 1         5 return undef;
29             }
30              
31             sub get {
32 1     1 0 7343 my $self = shift;
33              
34             # add chunks to buffer
35 1         7 $self->get_one_start(@_);
36              
37 1         2 warn "buffer:" . join('', map sprintf("%02x", ord $_), split //, $self->[HDLC_BUFFER]) . "\n" if DEBUG;
38            
39             # remove anything in the buffer before the first flag, it's officially noise
40 1         5 $self->[HDLC_BUFFER] =~ s/^[^\x7e]+//;
41              
42 1         2 my @packets;
43 1   33     19 PACKET: while (defined $self->[HDLC_BUFFER] and length $self->[HDLC_BUFFER]) {
44             # first char is always a \x7e
45 4         10 my $end = index $self->[HDLC_BUFFER], "\x7e", 1;
46 4 100       11 last PACKET if $end == -1;
47              
48 3         7 my $packet = substr $self->[HDLC_BUFFER], 1, $end - 1;
49 3         7 substr $self->[HDLC_BUFFER], 0, $end, '';
50 3 100       15 next PACKET if length($packet) < 4;
51              
52 2         33 $packet =~ tr/\x00-\x1f//d;
53 2         12 $packet =~ s/\x7d(.)/chr(ord($1) ^ 0x20)/seg; # the /s is important
  40         186  
54 2 50       8 next PACKET if length($packet) < 4; # can be too short again
55              
56             # remove flags (done), address and control and check the FCS
57             # we discard the packet on errors
58 2         12 my ($frame_address, $frame_control) = unpack "CC", $packet;
59 2         3 printf STDERR "frame: address=%02x control=%02x\n",
60             $frame_address, $frame_control
61             if DEBUG;
62              
63 2 50 33     17 next PACKET unless $frame_address == 0xff and $frame_control == 0x03;
64 2 50       25 next PACKET unless _frame_check($packet);
65              
66 2         22 push @packets, substr $packet, 2, -2;
67             }
68              
69 1         5 return [@packets];
70             }
71              
72             # Algorithm lifted from RFC1662
73             my @fcstab = (
74             0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
75             0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
76             0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
77             0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
78             0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
79             0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
80             0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
81             0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
82             0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
83             0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
84             0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
85             0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
86             0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
87             0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
88             0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
89             0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
90             0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
91             0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
92             0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
93             0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
94              
95             0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
96             0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
97             0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
98             0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
99             0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
100             0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
101             0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
102             0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
103             0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
104             0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
105             0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
106             0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
107             );
108             sub PPPINITFCS16 () { 0xffff } # Initial FCS value
109             sub PPPGOODFCS16 () { 0xf0b8 } # Good final FCS value
110              
111             sub _pppfcs16 {
112 25     25   4422 my $fcs = shift;
113 25         2666 $fcs = ($fcs >> 8) ^ $fcstab[($fcs ^ ord($1)) & 0xff] while $_[0] =~ m/(.)/g;
114 25         93 return $fcs & 0xffff;
115             }
116              
117             # not a method, one arg: the packet
118             sub _frame_check {
119 13     13   52 my $fcs = _pppfcs16(PPPINITFCS16, $_[0]);
120 13         18 printf STDERR "FCS: %04x on %d bytes\n", $fcs, length($_[0])
121             if DEBUG;
122 13         64 return $fcs == PPPGOODFCS16;
123             }
124              
125             1;
126             __END__