File Coverage

blib/lib/POE/Component/Client/Ident/Agent.pm
Criterion Covered Total %
statement 81 116 69.8
branch 15 34 44.1
condition 9 30 30.0
subroutine 13 19 68.4
pod 3 3 100.0
total 121 202 59.9


line stmt bran cond sub pod time code
1             # Author: Chris "BinGOs" Williams
2             #
3             # This module may be used, modified, and distributed under the same
4             # terms as Perl itself. Please see the license that came with your Perl
5             # distribution for details.
6             #
7              
8             package POE::Component::Client::Ident::Agent;
9              
10 2     2   116195 use strict;
  2         6  
  2         70  
11 2     2   11 use warnings;
  2         3  
  2         72  
12 2         17 use POE qw( Wheel::SocketFactory Wheel::ReadWrite Driver::SysRW
13 2     2   11 Filter::Line Filter::Stream Filter::Ident);
  2         5  
14 2     2   91 use Carp;
  2         3  
  2         97  
15 2     2   10 use Socket;
  2         12  
  2         1598  
16 2     2   12 use vars qw($VERSION);
  2         3  
  2         3305  
17              
18             $VERSION = '1.16';
19              
20             sub spawn {
21 1     1 1 16 my $package = shift;
22              
23 1         4 my ($peeraddr,$peerport,$sockaddr,$sockport,$identport,$buggyidentd,$timeout,$reference) = _parse_arguments(@_);
24            
25 1 50 33     27 unless ( $peeraddr and $peerport and $sockaddr and $sockport ) {
      33        
      33        
26 0         0 croak "Not enough arguments supplied to $package->spawn";
27             }
28              
29 1         5 my $self = $package->_new($peeraddr,$peerport,$sockaddr,$sockport,$identport,$buggyidentd,$timeout,$reference);
30              
31 1         12 $self->{session_id} = POE::Session->create(
32             object_states => [
33             $self => { shutdown => '_shutdown', },
34             $self => [qw(_start _sock_up _sock_down _sock_failed _parse_line _time_out)],
35             ],
36             )->ID();
37              
38 1         79 return $self;
39             }
40              
41             sub _new {
42 1     1   4 my ( $package, $peeraddr, $peerport, $sockaddr, $sockport, $identport, $buggyidentd, $timeout, $reference) = @_;
43 1         20 return bless { event_prefix => 'ident_agent_', peeraddr => $peeraddr, peerport => $peerport, sockaddr => $sockaddr, sockport => $sockport, identport => $identport, buggyidentd => $buggyidentd, timeout => $timeout, reference => $reference }, $package;
44             }
45              
46             sub session_id {
47 0     0 1 0 return $_[0]->{session_id};
48             }
49              
50             sub _start {
51 1     1   269 my ( $kernel, $self, $session, $sender ) = @_[ KERNEL, OBJECT, SESSION, SENDER ];
52              
53 1         3 $self->{sender} = $sender->ID();
54 1         7 $self->{session_id} = $session->ID();
55 1         12 $self->{ident_filter} = POE::Filter::Ident->new();
56 1         5 $kernel->delay( '_time_out' => $self->{timeout} );
57 1 50       129 $self->{socketfactory} = POE::Wheel::SocketFactory->new(
    50          
58             SocketDomain => AF_INET,
59             SocketType => SOCK_STREAM,
60             SocketProtocol => 'tcp',
61             RemoteAddress => $self->{'peeraddr'},
62             RemotePort => ( $self->{'identport'} ? ( $self->{'identport'} ) : ( 113 ) ),
63             SuccessEvent => '_sock_up',
64             FailureEvent => '_sock_failed',
65             ( $self->{sockaddr} ? (BindAddress => $self->{sockaddr}) : () ),
66             );
67 1         687 $self->{query_string} = $self->{peerport} . ", " . $self->{sockport};
68 1         8 $self->{query} = { PeerAddr => $self->{peeraddr}, PeerPort => $self->{peerport}, SockAddr => $self->{sockaddr}, SockPort => $self->{sockport}, Reference => $self->{reference} };
69 1         5 undef;
70             }
71              
72             sub _sock_up {
73 1     1   1187 my ($kernel,$self,$socket) = @_[KERNEL,OBJECT,ARG0];
74 1         2 my $filter;
75              
76 1         6 delete $self->{socketfactory};
77              
78 1 50       27 if ( $self->{buggyidentd} ) {
79 0         0 $filter = POE::Filter::Line->new();
80             } else {
81 1         10 $filter = POE::Filter::Line->new( Literal => "\x0D\x0A" );
82             }
83              
84 1         54 $self->{socket} = new POE::Wheel::ReadWrite
85             (
86             Handle => $socket,
87             Driver => POE::Driver::SysRW->new(),
88             Filter => $filter,
89             InputEvent => '_parse_line',
90             ErrorEvent => '_sock_down',
91             );
92              
93 1 50       302 $kernel->post( $self->{sender}, $self->{event_prefix} . 'error', $self->{query}, "UKNOWN-ERROR" ) unless $self->{socket};
94 1 50       10 $self->{socket}->put($self->{query_string}) if $self->{socket};
95 1         175 $kernel->delay( '_time_out' => $self->{timeout} );
96 1         160 undef;
97             }
98              
99             sub _sock_down {
100 0     0   0 my ($kernel,$self) = @_[KERNEL,OBJECT];
101              
102 0 0       0 $kernel->post( $self->{sender}, $self->{event_prefix} . 'error', $self->{query}, "UKNOWN-ERROR" ) unless $self->{had_a_response};
103 0         0 delete $self->{socket};
104 0         0 $kernel->delay( '_time_out' => undef );
105 0         0 undef;
106             }
107              
108              
109             sub _sock_failed {
110 0     0   0 my ($kernel, $self) = @_[KERNEL,OBJECT];
111              
112 0         0 $kernel->post( $self->{sender}, $self->{event_prefix} . 'error', $self->{query}, "UKNOWN-ERROR" );
113 0         0 $kernel->delay( '_time_out' => undef );
114 0         0 delete $self->{socketfactory};
115 0         0 undef;
116             }
117              
118             sub _time_out {
119 0     0   0 my ($kernel,$self) = @_[KERNEL,OBJECT];
120              
121 0         0 $kernel->post( $self->{sender}, $self->{event_prefix} . 'error', $self->{query}, "UKNOWN-ERROR" );
122 0         0 delete $self->{socketfactory};
123 0         0 delete $self->{socket};
124 0         0 undef;
125             }
126              
127             sub _parse_line {
128 1     1   2861 my ($kernel,$self,$line) = @_[KERNEL,OBJECT,ARG0];
129 1         17 my @cooked;
130              
131 1         3 @cooked = @{$self->{ident_filter}->get( [$line] )};
  1         9  
132              
133 1         9 foreach my $ev (@cooked) {
134 1 50       6 if ( $ev->{name} eq 'barf' ) {
135             # Filter choaked for whatever reason
136 0         0 $kernel->post( $self->{sender}, $self->{event_prefix} . 'error', $self->{query}, "UKNOWN-ERROR" );
137             } else {
138 1         4 $ev->{name} = $self->{event_prefix} . $ev->{name};
139 1         3 my ($port1, $port2, @args) = @{$ev->{args}};
  1         11  
140 1 50       6 if ( $self->_port_pair_matches( $port1, $port2 ) ) {
141 1         5 $kernel->post( $self->{sender}, $ev->{name}, $self->{query}, @args );
142             } else {
143 0         0 $kernel->post( $self->{sender}, $self->{event_prefix} . 'error', $self->{query}, "UKNOWN-ERROR" );
144             }
145             }
146             }
147 1         97 $kernel->delay( '_time_out' => undef );
148 1         114 $self->{had_a_response} = 1;
149 1         9 delete $self->{socket};
150 1         260 undef;
151             }
152              
153             sub shutdown {
154 0     0 1 0 my $self = shift;
155 0         0 $poe_kernel->call( $self->session_id() => 'shutdown' => @_ );
156             }
157              
158             sub _shutdown {
159 0     0   0 my ($kernel,$self) = @_[KERNEL,OBJECT];
160 0         0 $self->{had_a_response} = 1;
161 0         0 delete $self->{socket};
162 0         0 $kernel->delay( '_time_out' => undef );
163 0         0 undef;
164             }
165              
166             sub _port_pair_matches {
167 1     1   3 my ($self) = shift;
168 1         1 my ($port1,$port2) = @_;
169 1 50 33     15 return 1 if $port1 == $self->{peerport} and $port2 == $self->{sockport};
170 0         0 return 0;
171             }
172              
173             sub _parse_arguments {
174 1     1   7 my ( %hash ) = @_;
175 1         2 my @returns;
176              
177             # If we get a socket it takes precedence over any other arguments
178             SWITCH: {
179 1 50       2 if ( defined ( $hash{'Reference'} ) ) {
  1         10  
180 1         3 $returns[7] = $hash{'Reference'};
181             }
182 1 50       5 if ( defined ( $hash{'IdentPort'} ) ) {
183 1         2 $returns[4] = $hash{'IdentPort'};
184             }
185 1 50 33     5 if ( defined ( $hash{'BuggyIdentd'} ) and $hash{'BuggyIdentd'} == 1 ) {
186 0         0 $returns[5] = $hash{'BuggyIdentd'};
187             }
188 1 0 0     5 if ( defined ( $hash{'TimeOut'} ) and ( $hash{'TimeOut'} > 5 or $hash{'TimeOut'} < 30 ) ) {
      33        
189 0         0 $returns[6] = $hash{'TimeOut'};
190             }
191 1 50       4 $returns[6] = 30 unless ( defined ( $returns[6] ) );
192 1 50       4 if ( defined ( $hash{'Socket'} ) ) {
193 0         0 $returns[0] = inet_ntoa( (unpack_sockaddr_in( getpeername $hash{'Socket'} ))[1] );
194 0         0 $returns[1] = (unpack_sockaddr_in( getpeername $hash{'Socket'} ))[0];
195 0         0 $returns[2] = inet_ntoa( (unpack_sockaddr_in( getsockname $hash{'Socket'} ))[1] );
196 0         0 $returns[3] = (unpack_sockaddr_in( getsockname $hash{'Socket'} ))[0];
197 0         0 last SWITCH;
198             }
199 1 50 33     18 if ( defined ( $hash{'PeerAddr'} ) and defined ( $hash{'PeerPort'} ) and defined ( $hash{'SockAddr'} ) and defined ( $hash{'SockAddr'} ) ) {
      33        
      33        
200 1         1 $returns[0] = $hash{'PeerAddr'};
201 1         2 $returns[1] = $hash{'PeerPort'};
202 1         2 $returns[2] = $hash{'SockAddr'};
203 1         8 $returns[3] = $hash{'SockPort'};
204 1         3 last SWITCH;
205             }
206             }
207 1         6 return @returns;
208             }
209              
210             'Who are you?';
211              
212             __END__