File Coverage

blib/lib/POE/Component/Client/opentick/Util.pm
Criterion Covered Total %
statement 62 62 100.0
branch 11 16 68.7
condition 2 2 100.0
subroutine 16 16 100.0
pod 9 9 100.0
total 100 105 95.2


line stmt bran cond sub pod time code
1             package POE::Component::Client::opentick::Util;
2             #
3             # opentick.com POE client
4             #
5             # Low-level utility routines
6             #
7             # infi/2008
8             #
9             # $Id: Util.pm 56 2009-01-08 16:51:14Z infidel $
10             #
11             # Full POD documentation after __END__
12             #
13              
14 5     5   89603 use strict;
  5         12  
  5         5998  
15 5     5   33 use warnings;
  5         9  
  5         202  
16 5     5   115 use Carp qw( carp );
  5         10  
  5         287  
17 5     5   1517 use Data::Dumper;
  5         14558  
  5         257  
18              
19 5     5   3954 use POE::Component::Client::opentick::Error;
  5         15  
  5         300  
20              
21 5     5   30 use vars qw( $VERSION $TRUE $FALSE );
  5         10  
  5         861  
22              
23             BEGIN {
24 5     5   26 require Exporter;
25 5         71 our @ISA = qw( Exporter );
26 5         17 our @EXPORT = qw( pack_binary unpack_binary count_fields check_fields
27             dump_hex pack_macaddr is_error pack_bytes
28             asc2longlong );
29 5         4332 ($VERSION) = q$Revision: 56 $ =~ /(\d+)/;
30             }
31              
32             ###
33             ### Variables
34             ###
35              
36             *TRUE = \1;
37             *FALSE = \0;
38              
39             # NOTE: This is not complete, nor is it intended to be.
40             # Probably not platform-safe, either.
41             my $pack_bytes = {
42             x => 1, a => 1, A => 1, c => 1,
43             C => 1, s => 2, S => 2, i => 4,
44             I => 4, l => 4, L => 4, n => 2,
45             N => 4, v => 2, V => 4, f => 4,
46             d => 8, p => 4, P => 4,
47             };
48              
49             ###
50             ### Functions
51             ###
52              
53             sub pack_binary
54             {
55 13     13 1 33 my( $pack_tmpl, @fields ) = @_;
56              
57 13         29 my $field_count = count_fields( $pack_tmpl );
58 13 50       41 throw( "Require $field_count fields for template '$pack_tmpl', but " .
59             "received " . scalar( @fields ) )
60             unless( check_fields( $field_count, @fields ) );
61 13         63 my $string = pack( $pack_tmpl, @fields );
62              
63 13         50 return( $string );
64             }
65              
66             sub unpack_binary
67             {
68 10     10 1 21 my( $pack_tmpl, $string ) = @_;
69              
70 10         22 my $field_count = count_fields( $pack_tmpl );
71 10         56 my( @fields ) = unpack( $pack_tmpl, $string );
72              
73             # NOTE: Some incoming packets are of variable length, so this is bogus.
74             # throw( "Should expand $field_count fields from template '$pack_tmpl', " .
75             # "but got " . scalar( @fields ) )
76             # unless( check_fields( $field_count, @fields ) );
77              
78 10 50       55 return( wantarray ? @fields : $fields[0] );
79             }
80              
81             # NOTE: Not complete for all pack templates.
82             sub count_fields
83             {
84 26     26 1 59 my( $pack_tmpl ) = @_;
85              
86 26         204 my $count = grep { ! /^x/ } split( /\s+/, $pack_tmpl );
  106         239  
87              
88 26         69 return( $count );
89             }
90              
91             sub check_fields
92             {
93 19     19 1 48 my( $count, @fields ) = @_;
94              
95 19         28 my $field_count = grep { defined } @fields;
  65         106  
96              
97 19 100       151 return( $count == $field_count ? $TRUE : $FALSE );
98             }
99              
100             sub dump_hex
101             {
102 1     1 1 2 my( $data ) = @_;
103              
104             # Stolen from perlpacktut.pod, because I'm lazy.
105 1         2 my $i;
106 1 100       48 my $hex = join( '', map( ++$i % 16 ? "$_ " : "$_\n",
    50          
107             unpack( 'H2' x length( $data ), $data ) ),
108             length( $data ) % 16 ? "\n" : '' );
109              
110 1         7 return( $hex );
111             }
112              
113             sub pack_macaddr
114             {
115 2     2 1 5 my ( $macaddr ) = @_;
116              
117             # FIXME: ensure validity
118 2 50       24 check_fields( 6, $macaddr =~ m/([0-9a-f]{2})[:-]?/ig )
119             or throw( "Invalid MAC address: $macaddr; expected in " .
120             "xx:xx:xx:xx:xx:xx format." );
121              
122 2         19 $macaddr =~ s/[:-]//g;
123              
124 2         20 return( pack( 'H*', $macaddr ) );
125             }
126              
127             sub is_error
128             {
129 6     6 1 674 my( $object ) = @_;
130              
131 6 100       45 return( ref( $object ) eq 'POE::Component::Client::opentick::Error'
132             ? $TRUE
133             : $FALSE );
134             }
135              
136             # NOTE: This is not complete, nor is it intended to be.
137             sub pack_bytes
138             {
139 1     1 1 405 my( $template, $input ) = @_;
140 1 50       4 return 0 unless( $template );
141              
142 1         15 my @tokens = $template =~ m#([A-Za-z]\d*)+\s*#g;
143              
144 1         2 my $count = 0;
145 1         3 for( @tokens )
146             {
147 12         60 my( $digit, $repeat ) = m#(.)(\d*)#;
148 12   100     28 $repeat ||= 1;
149 12         18 $count += $pack_bytes->{$digit} * $repeat;
150             }
151              
152 1         6 return( $count );
153             }
154              
155             sub asc2longlong
156             {
157 5     5 1 12 my( $string ) = @_;
158              
159 5         36 my( $i1, $i2 ) = unpack( 'VV', pack( 'a8', $string ) );
160 5         15 my $ll = ( $i2 * ( 2**32 )) + $i1;
161              
162 5         28 return( $ll );
163             }
164              
165             1;
166              
167             __END__