diff options
author | Guilhem Moulin <guilhem@fripost.org> | 2015-09-17 22:05:09 +0200 |
---|---|---|
committer | Guilhem Moulin <guilhem@fripost.org> | 2015-09-21 01:01:25 +0200 |
commit | 612b9e2102e1907709dde325f91d5fdf70ed2534 (patch) | |
tree | 007d69ddd0998924ce81493b2a49a9076d8f020b | |
parent | 683a3973a32ee3618824d08ed7ee6cfc7ee9ab02 (diff) |
Use TCP keepalive to detect dead peers.
-rw-r--r-- | Changelog | 3 | ||||
-rwxr-xr-x | interimap | 1 | ||||
-rw-r--r-- | lib/Net/IMAP/InterIMAP.pm | 20 |
3 files changed, 21 insertions, 3 deletions
@@ -22,9 +22,6 @@ interimap (0.2) upstream; IPv6. (Both are core Perl module.) * Add a configuration option 'proxy' to proxy TCP connections to the IMAP server. - * Don't set SO_KEEPALIVE on the socket. This is most likely useless - in our case since the TCP keepalive time is usually much higher than - the IMAP timeout. * Set X.509 certificate purpose to 'SSL Server' for SSL_verify=YES. * Display the certificate chain, SSL protocol and cipher in debug mode. @@ -248,6 +248,7 @@ foreach my $name (qw/local remote/) { $config{name} = $name; $config{'logger-fd'} = $LOGGER_FD if defined $LOGGER_FD; $config{'compress'} //= ($name eq 'local' ? 0 : 1); + $config{keepalive} = 1 if $CONFIG{watch} and $config{type} ne 'tunnel'; $IMAP->{$name} = { client => Net::IMAP::InterIMAP::->new(%config) }; my $client = $IMAP->{$name}->{client}; diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm index bf33294..d6c46a8 100644 --- a/lib/Net/IMAP/InterIMAP.pm +++ b/lib/Net/IMAP/InterIMAP.pm @@ -228,6 +228,9 @@ our $IMAP_text; # # - 'logger-fd': An optional filehandle to use for debug output. # +# - 'keepalive': Whether to enable sending of keep-alive messages. +# (type=imap or type=imaps). +# sub new($%) { my $class = shift; my $self = { @_ }; @@ -289,6 +292,23 @@ sub new($%) { } my $socket = defined $self->{proxy} ? $self->_proxify(@$self{qw/proxy host port/}) : $self->_tcp_connect(@$self{qw/host port/}); + my ($cnt, $intvl) = (3, 5); + if (defined $self->{keepalive}) { + # detect dead peers and drop the connection after 60 secs + $cnt*$intvl + setsockopt($socket, Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1) + or $self->fail("Can't setsockopt SO_KEEPALIVE: $!"); + setsockopt($socket, Socket::IPPROTO_TCP, Socket::TCP_KEEPIDLE, 60) + or $self->fail("Can't setsockopt TCP_KEEPIDLE: $!"); + setsockopt($socket, Socket::IPPROTO_TCP, Socket::TCP_KEEPCNT, $cnt) + or $self->fail("Can't setsockopt TCP_KEEPCNT: $!"); + setsockopt($socket, Socket::IPPROTO_TCP, Socket::TCP_KEEPINTVL, $intvl) + or $self->fail("Can't setsockopt TCP_KEEPINTVL: $!"); + } + # Abort after 15secs if write(2) isn't acknowledged + # XXX Socket::TCP_USER_TIMEOUT isn't defined. + # `grep TCP_USER_TIMEOUT /usr/include/linux/tcp.h` gives 18 + setsockopt($socket, Socket::IPPROTO_TCP, 18, 1000 * $cnt * $intvl) + or $self->fail("Can't setsockopt TCP_USER_TIMEOUT: $!"); $self->_start_ssl($socket) if $self->{type} eq 'imaps'; $self->{$_} = $socket for qw/STDOUT STDIN/; |