File Coverage

lib/Pcore/AE/Patch.pm
Criterion Covered Total %
statement 18 70 25.7
branch 0 28 0.0
condition 0 13 0.0
subroutine 6 10 60.0
pod 0 1 0.0
total 24 122 19.6


line stmt bran cond sub pod time code
1             package Pcore::AE::Patch;
2              
3 5     5   32 use Pcore;
  5         10  
  5         31  
4 5     5   1802 use Socket qw(AF_INET AF_UNIX SOCK_STREAM SOCK_DGRAM SOL_SOCKET SO_REUSEADDR);
  5         15426  
  5         862  
5 5     5   39 use AnyEvent qw[];
  5         8  
  5         87  
6 5     5   1850 use AnyEvent::Socket qw[];
  5         87679  
  5         187  
7 5     5   45 use AnyEvent::Util qw[guard];
  5         11  
  5         660  
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         9  
  5         4005  
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           AnyEvent::Socket::_tcp_bind_orig(@_);
109              
110 0           return;
111             }
112              
113             1;
114             ## -----SOURCE FILTER LOG BEGIN-----
115             ##
116             ## PerlCritic profile "pcore-script" policy violations:
117             ## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
118             ## | Sev. | Lines | Policy |
119             ## |======+======================+================================================================================================================|
120             ## | 3 | 16, 23 | Variables::ProtectPrivateVars - Private variable used |
121             ## |------+----------------------+----------------------------------------------------------------------------------------------------------------|
122             ## | 3 | 28 | Subroutines::ProhibitManyArgs - Too many arguments |
123             ## |------+----------------------+----------------------------------------------------------------------------------------------------------------|
124             ## | 3 | 108 | Subroutines::ProtectPrivateSubs - Private subroutine/method used |
125             ## |------+----------------------+----------------------------------------------------------------------------------------------------------------|
126             ## | 2 | 84 | ValuesAndExpressions::ProhibitEscapedCharacters - Numeric escapes in interpolated string |
127             ## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
128             ##
129             ## -----SOURCE FILTER LOG END-----
130             __END__
131             =pod
132              
133             =encoding utf8
134              
135             =head1 NAME
136              
137             Pcore::AE::Patch
138              
139             =head1 SYNOPSIS
140              
141             =head1 DESCRIPTION
142              
143             =head1 ATTRIBUTES
144              
145             =head1 METHODS
146              
147             =head1 SEE ALSO
148              
149             =cut