File Coverage

lib/Pcore/AE/Patch.pm
Criterion Covered Total %
statement 18 69 26.0
branch 0 28 0.0
condition 0 13 0.0
subroutine 6 10 60.0
pod 0 1 0.0
total 24 121 19.8


line stmt bran cond sub pod time code
1             package Pcore::AE::Patch;
2              
3 5     5   30 use Pcore;
  5         10  
  5         31  
4 5     5   1700 use Socket qw(AF_INET AF_UNIX SOCK_STREAM SOCK_DGRAM SOL_SOCKET SO_REUSEADDR);
  5         14452  
  5         826  
5 5     5   36 use AnyEvent qw[];
  5         10  
  5         82  
6 5     5   1852 use AnyEvent::Socket qw[];
  5         83139  
  5         200  
7 5     5   46 use AnyEvent::Util qw[guard];
  5         10  
  5         693  
8              
9             our $TTL = 60; # cache positive responses for 60 sec.
10             our $NEGATIVE_TTL = 5; # cache negative responses for 5 sec.
11             our $MAX_CACHE_SIZE = 10_000;
12              
13             our $SOCKADDR_CACHE = {};
14              
15             *AnyEvent::Socket::resolve_sockaddr_orig = \&AnyEvent::Socket::resolve_sockaddr;
16             *AnyEvent::Socket::_tcp_bind_orig = \&AnyEvent::Socket::_tcp_bind;
17              
18             # install hooks
19             {
20 5     5   32 no warnings qw[redefine];
  5         10  
  5         3828  
21              
22             *AnyEvent::Socket::resolve_sockaddr = \&resolve_sockaddr;
23             *AnyEvent::Socket::_tcp_bind = \&_tcp_bind;
24             }
25              
26             # support for linux abstract UDS
27             # cache requests
28 0     0 0   sub resolve_sockaddr ( $node, $service, $proto, $family, $type, $cb ) : prototype($$$$$$) {
  0            
  0            
  0            
  0            
  0            
  0            
  0            
29 0           state $callback = {};
30              
31 0 0         if ( $node eq 'unix/' ) {
32              
33             # error
34 0 0 0       return $cb->() if $family || $service !~ /^[\/\x00]/sm;
35              
36 0 0         return $cb->( [ AF_UNIX, defined $type ? $type : SOCK_STREAM, 0, Socket::pack_sockaddr_un $service] );
37             }
38              
39 0   0       my $cache_key = join q[-], map { $_ // q[] } @_[ 0 .. $#_ - 1 ];
  0            
40              
41 0 0         if ( exists $SOCKADDR_CACHE->{$cache_key} ) {
42 0 0         if ( $SOCKADDR_CACHE->{$cache_key}->[0] > time ) {
43 0           $cb->( $SOCKADDR_CACHE->{$cache_key}->[1]->@* );
44              
45 0           return;
46             }
47             else {
48 0           delete $SOCKADDR_CACHE->{$cache_key};
49             }
50             }
51              
52 0           push $callback->{$cache_key}->@*, $cb;
53              
54 0 0         return if $callback->{$cache_key}->@* > 1;
55              
56 0     0     AnyEvent::Socket::resolve_sockaddr_orig(
57             @_[ 0 .. $#_ - 1 ],
58 0           sub (@) {
59              
60             # cleanup cache
61 0 0         $SOCKADDR_CACHE = {} if keys $SOCKADDR_CACHE->%* > $MAX_CACHE_SIZE;
62              
63             # cache response
64 0 0         $SOCKADDR_CACHE->{$cache_key} = [ time + ( @_ ? $TTL : $NEGATIVE_TTL ), \@_ ];
65              
66             # fire callbacks
67 0           while ( my $cb = shift $callback->{$cache_key}->@* ) {
68 0           $cb->(@_);
69             }
70              
71 0           delete $callback->{$cache_key};
72              
73 0           return;
74             }
75 0           );
76              
77 0           return;
78             }
79              
80             # support for linux abstract UDS
81 0     0     sub _tcp_bind ( $host, $service, $done, $prepare = undef ) : prototype($$$;$) {
  0            
  0            
  0            
  0            
  0            
82              
83             # hook for Linux abstract Unix Domain Sockets (UDS)
84 0 0 0       if ( defined $host && $host eq 'unix/' && substr( $service, 0, 1 ) eq "\x00" ) {
      0        
85 0           state $ipn_uds = pack 'S', AF_UNIX;
86              
87 0           my %state;
88              
89 0 0         socket $state{fh}, AF_UNIX, SOCK_STREAM, 0 or die "tcp_server/socket: $!";
90              
91 0 0         bind $state{fh}, AnyEvent::Socket::pack_sockaddr $service, $ipn_uds or die "bind: $!";
92              
93 0           AnyEvent::fh_unblock $state{fh};
94              
95 0           my $len;
96              
97 0 0         $len = $prepare->( $state{fh}, AnyEvent::Socket::format_address $ipn_uds, $service ) if $prepare;
98              
99 0   0       $len ||= 128;
100              
101 0 0         listen $state{fh}, $len or die "listen: $!";
102              
103 0           $done->( \%state );
104              
105 0 0   0     return defined wantarray ? guard { %state = () } : ();
  0            
106             }
107              
108 0           return AnyEvent::Socket::_tcp_bind_orig(@_);
109             }
110              
111             1;
112             ## -----SOURCE FILTER LOG BEGIN-----
113             ##
114             ## PerlCritic profile "pcore-script" policy violations:
115             ## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
116             ## | Sev. | Lines | Policy |
117             ## |======+======================+================================================================================================================|
118             ## | 3 | 16, 23 | Variables::ProtectPrivateVars - Private variable used |
119             ## |------+----------------------+----------------------------------------------------------------------------------------------------------------|
120             ## | 3 | 28 | Subroutines::ProhibitManyArgs - Too many arguments |
121             ## |------+----------------------+----------------------------------------------------------------------------------------------------------------|
122             ## | 3 | 108 | Subroutines::ProtectPrivateSubs - Private subroutine/method used |
123             ## |------+----------------------+----------------------------------------------------------------------------------------------------------------|
124             ## | 2 | 84 | ValuesAndExpressions::ProhibitEscapedCharacters - Numeric escapes in interpolated string |
125             ## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
126             ##
127             ## -----SOURCE FILTER LOG END-----
128             __END__
129             =pod
130              
131             =encoding utf8
132              
133             =head1 NAME
134              
135             Pcore::AE::Patch
136              
137             =head1 SYNOPSIS
138              
139             =head1 DESCRIPTION
140              
141             =head1 ATTRIBUTES
142              
143             =head1 METHODS
144              
145             =head1 SEE ALSO
146              
147             =cut