File Coverage

blib/lib/XAS/Lib/Mixins/Keepalive.pm
Criterion Covered Total %
statement 9 39 23.0
branch 0 14 0.0
condition n/a
subroutine 3 7 42.8
pod 2 2 100.0
total 14 62 22.5


line stmt bran cond sub pod time code
1             package XAS::Lib::Mixins::Keepalive;
2              
3             our $VERSION = '0.01';
4              
5             our $TCP_KEEPCNT = 0;
6             our $TCP_KEEPIDLE = 0;
7             our $TCP_KEEPINTVL = 0;
8              
9 1     1   1375 use Try::Tiny;
  1         1  
  1         51  
10 1     1   4 use Socket ':all';
  1         1  
  1         942  
11              
12             use XAS::Class
13 1         5 debug => 0,
14             version => $VERSION,
15             base => 'XAS::Base',
16             utils => ':validation',
17             accessors => 'tcp_keepidle tcp_keepcnt tcp_keepintvl',
18             mixins => 'init_keepalive enable_keepalive tcp_keepidle tcp_keepcnt tcp_keepintvl',
19 1     1   5 ;
  1         1  
20              
21             # ----------------------------------------------------------------------
22             # Public Methods
23             # ----------------------------------------------------------------------
24              
25             sub enable_keepalive {
26 0     0 1   my $self = shift;
27 0           my ($socket) = validate_params(\@_, [1]);
28              
29             # turn keepalive on, this should send a keepalive
30             # packet once every 2 hours according to the RFC.
31              
32 0           setsockopt($socket, SOL_SOCKET, SO_KEEPALIVE, 1);
33              
34             # adjust the system defaults, all values are in seconds.
35             # so this does the following:
36             # every 15 minutes send up to 3 packets at 5 second intervals
37             # if no reply, the connection is down.
38              
39 0           setsockopt($socket, IPPROTO_TCP, $TCP_KEEPINTVL, $self->tcp_keepintvl);
40 0           setsockopt($socket, IPPROTO_TCP, $TCP_KEEPIDLE, $self->tcp_keepidle);
41 0           setsockopt($socket, IPPROTO_TCP, $TCP_KEEPCNT, $self->tcp_keepcnt);
42              
43             }
44              
45             # ----------------------------------------------------------------------
46             # Private Methods
47             # ----------------------------------------------------------------------
48              
49             sub init_keepalive {
50 0     0 1   my $self = shift;
51 0           my $p = validate_params(\@_, {
52             -tcp_keepcnt => { optional => 1, default => 3 }, # number of packets
53             -tcp_keepidle => { optional => 1, default => 900 }, # 15 minutes
54             -tcp_keepintvl => { optional => 1, default => 5 }, # interval seconds
55             });
56            
57 0           $self->{tcp_keepcnt} = $p->{tcp_keepcnt};
58 0           $self->{tcp_keepidle} = $p->{tcp_keepidle};
59 0           $self->{tcp_keepintvl} = $p->{tcp_keepintvl};
60            
61             # implement socket level keepalive, what a mess...
62              
63 0 0         if ( $] < 5.014 ) { # check perl's version
64              
65             # at this point we can only support the below. if you have
66             # access to your systems header files, you could provide
67             # the following values. I would be happy to include them.
68              
69 0 0         if ($^O eq "aix") { # from /usr/include/netinet/tcp.h
    0          
    0          
70              
71 0           $TCP_KEEPIDLE = 0x11;
72 0           $TCP_KEEPINTVL = 0x12;
73 0           $TCP_KEEPCNT = 0x13;
74              
75             } elsif ($^O eq "linux") { # from /usr/include/netinet/tcp.h
76              
77 0           $TCP_KEEPIDLE = 4;
78 0           $TCP_KEEPINTVL = 5;
79 0           $TCP_KEEPCNT = 6;
80              
81             } elsif ($^O eq 'vms') { # from TCP in sys$library:decc$rtldef.tlb
82              
83 0           $TCP_KEEPIDLE = 0x04;
84 0           $TCP_KEEPINTVL = 0x05;
85 0           $TCP_KEEPCNT = 0x06;
86              
87             }
88              
89             } else {
90              
91             try {
92              
93             # hmmm, maybe perl will do it for us. checking to see if the
94             # platform implements these macros.
95              
96 0 0   0     $TCP_KEEPCNT = Socket::TCP_KEEPCNT() if (UNIVERSAL::can('Socket', 'TCP_KEEPCNT'));
97 0 0         $TCP_KEEPIDLE = Socket::TCP_KEEPIDLE() if (UNIVERSAL::can('Socket', 'TCP_KEEPIDLE'));
98 0 0         $TCP_KEEPINTVL = Socket::TCP_KEEPINTVL() if (UNIVERSAL::can('Socket', 'TCP_KEEPINTVL'));
99              
100             } catch {
101              
102             # nope, guess not...
103              
104 0     0     my $ex = $_;
105 0           my ($err) = m/(.*,)/;
106 0           chop($err);
107              
108 0           $self->log->warn(lcfirst($err));
109              
110 0           };
111              
112             }
113              
114             }
115              
116             1;
117              
118             __END__