File Coverage

blib/lib/POE/Wheel/ListenAccept.pm
Criterion Covered Total %
statement 57 62 91.9
branch 11 24 45.8
condition 1 3 33.3
subroutine 12 14 85.7
pod 3 4 75.0
total 84 107 78.5


line stmt bran cond sub pod time code
1             package POE::Wheel::ListenAccept;
2              
3 2     2   8 use strict;
  2         2  
  2         63  
4              
5 2     2   7 use vars qw($VERSION @ISA);
  2         2  
  2         91  
6             $VERSION = '1.366'; # NOTE - Should be #.### (three decimal places)
7              
8 2     2   7 use Carp qw( croak carp );
  2         2  
  2         88  
9 2     2   8 use Symbol qw( gensym );
  2         3  
  2         63  
10              
11 2     2   7 use POSIX qw(:fcntl_h);
  2         6  
  2         10  
12 2     2   650 use Errno qw(EWOULDBLOCK);
  2         3  
  2         102  
13 2     2   9 use POE qw( Wheel );
  2         2  
  2         16  
14             push @ISA, qw(POE::Wheel);
15              
16             sub SELF_HANDLE () { 0 }
17             sub SELF_EVENT_ACCEPT () { 1 }
18             sub SELF_EVENT_ERROR () { 2 }
19             sub SELF_UNIQUE_ID () { 3 }
20             sub SELF_STATE_ACCEPT () { 4 }
21              
22 0     0 0 0 sub CRIMSON_SCOPE_HACK ($) { 0 }
23              
24             #------------------------------------------------------------------------------
25              
26             sub new {
27 2     2 1 1833 my $type = shift;
28 2         9 my %params = @_;
29              
30 2 50 33     16 croak "wheels no longer require a kernel reference as their first parameter"
31             if (@_ && (ref($_[0]) eq 'POE::Kernel'));
32              
33 2 50       6 croak "$type requires a working Kernel" unless defined $poe_kernel;
34              
35 2 50       6 croak "Handle required" unless defined $params{Handle};
36 2 50       6 croak "AcceptEvent required" unless defined $params{AcceptEvent};
37              
38 2         12 my $self = bless [ $params{Handle}, # SELF_HANDLE
39             delete $params{AcceptEvent}, # SELF_EVENT_ACCEPT
40             delete $params{ErrorEvent}, # SELF_EVENT_ERROR
41             &POE::Wheel::allocate_wheel_id(), # SELF_UNIQUE_ID
42             undef, # SELF_STATE_ACCEPT
43             ], $type;
44             # register private event handlers
45 2         7 $self->_define_accept_state();
46 2         10 $poe_kernel->select($self->[SELF_HANDLE], $self->[SELF_STATE_ACCEPT]);
47              
48 2         11 $self;
49             }
50              
51             #------------------------------------------------------------------------------
52              
53             sub event {
54 2     2 1 9 my $self = shift;
55 2 50       9 push(@_, undef) if (scalar(@_) & 1);
56              
57 2         14 while (@_) {
58 4         9 my ($name, $event) = splice(@_, 0, 2);
59              
60 4 100       12 if ($name eq 'AcceptEvent') {
    50          
61 2 50       6 if (defined $event) {
62 2         7 $self->[SELF_EVENT_ACCEPT] = $event;
63             }
64             else {
65 0         0 carp "AcceptEvent requires an event name. ignoring undef";
66             }
67             }
68             elsif ($name eq 'ErrorEvent') {
69 2         9 $self->[SELF_EVENT_ERROR] = $event;
70             }
71             else {
72 0         0 carp "ignoring unknown ListenAccept parameter '$name'";
73             }
74             }
75             }
76              
77             #------------------------------------------------------------------------------
78              
79             sub _define_accept_state {
80 2     2   3 my $self = shift;
81             # stupid closure trick
82 2         13 my $event_accept = \$self->[SELF_EVENT_ACCEPT];
83 2         3 my $event_error = \$self->[SELF_EVENT_ERROR];
84 2         3 my $handle = $self->[SELF_HANDLE];
85 2         10 my $unique_id = $self->[SELF_UNIQUE_ID];
86             # register the select-read handler
87             $poe_kernel->state
88             ( $self->[SELF_STATE_ACCEPT] = ref($self) . "($unique_id) -> select read",
89             sub {
90             # prevents SEGV
91 10     10   12 0 && CRIMSON_SCOPE_HACK('<');
92              
93             # subroutine starts here
94 10         23 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
95              
96 10         37 my $new_socket = gensym;
97 10         312 my $peer = accept($new_socket, $handle);
98              
99 10 50       20 if ($peer) {
    0          
100 10         78 $k->call($me, $$event_accept, $new_socket, $peer, $unique_id);
101             }
102             elsif ($! != EWOULDBLOCK) {
103 0 0       0 $$event_error &&
104             $k->call($me, $$event_error, 'accept', ($!+0), $!, $unique_id);
105             }
106             }
107 2         22 );
108             }
109              
110             #------------------------------------------------------------------------------
111              
112             sub DESTROY {
113 2     2   28 my $self = shift;
114             # remove tentacles from our owner
115 2         13 $poe_kernel->select($self->[SELF_HANDLE]);
116              
117 2 50       12 if ($self->[SELF_STATE_ACCEPT]) {
118 2         14 $poe_kernel->state($self->[SELF_STATE_ACCEPT]);
119 2         6 undef $self->[SELF_STATE_ACCEPT];
120             }
121              
122 2         15 &POE::Wheel::free_wheel_id($self->[SELF_UNIQUE_ID]);
123             }
124              
125             #------------------------------------------------------------------------------
126              
127             sub ID {
128 0     0 1   return $_[0]->[SELF_UNIQUE_ID];
129             }
130              
131             1;
132              
133             __END__