1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Enable socket keep-alive on older Perl versions.

The prior method depended on IO:Socket:SSL to push the keep-alive options down to the socket but it only worked for recent versions of the module.

Instead, create the socket directly using IO::Socket::IP if available or IO:Socket:INET as a fallback.  The keep-alive option is set directly on the socket before it is passed to IO:Socket:SSL.

Contributed by Marc Cousin.
This commit is contained in:
Marc Cousin 2019-02-28 14:33:29 +02:00 committed by David Steele
parent 0913523096
commit cb3b4fa24b
4 changed files with 55 additions and 25 deletions

View File

@ -45,6 +45,14 @@
<p>The <cmd>archive-get</cmd> command is implemented entirely in C.</p>
</release-item>
<release-item>
<release-item-contributor-list>
<release-item-contributor id="marc.cousin"/>
</release-item-contributor-list>
<p>Enable socket keep-alive on older <proper>Perl</proper> versions.</p>
</release-item>
<release-item>
<release-item-contributor-list>
<release-item-ideator id="james.badger"/>
@ -6543,6 +6551,11 @@
<contributor-id type="github">mhagander</contributor-id>
</contributor>
<contributor id="marc.cousin">
<contributor-name-display>Marc Cousin</contributor-name-display>
<contributor-id type="github">marco44</contributor-id>
</contributor>
<contributor id="markus.nullmeier">
<contributor-name-display>Markus Nullmeier</contributor-name-display>
<contributor-id type="github">mnullmei</contributor-id>

View File

@ -97,25 +97,33 @@ sub new
# Connect to the server
my $oSocket;
if (eval{require IO::Socket::IP})
{
$oSocket = IO::Socket::IP->new(PeerHost => $strHost, PeerPort => $iPort)
or confess &log(ERROR, "unable to create socket: $@", ERROR_HOST_CONNECT);
}
else
{
require IO::Socket::INET;
$oSocket = IO::Socket::INET->new(PeerHost => $strHost, PeerPort => $iPort)
or confess &log(ERROR, "unable to create socket: $@", ERROR_HOST_CONNECT);
}
setsockopt($oSocket, SOL_SOCKET,SO_KEEPALIVE, 1)
or confess &log(ERROR, "unable to set socket keepalive: $@", ERROR_HOST_CONNECT);
eval
{
$oSocket = IO::Socket::SSL->new(
PeerHost => $strHost, PeerPort => $iPort, SSL_verify_mode => $bVerifySsl ? SSL_VERIFY_PEER : SSL_VERIFY_NONE,
SSL_ca_path => $strCaPath, SSL_ca_file => $strCaFile, Sockopts => [[SOL_SOCKET, SO_KEEPALIVE]]);
return 1;
IO::Socket::SSL->start_SSL(
$oSocket, SSL_verify_mode => $bVerifySsl ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, SSL_ca_path => $strCaPath,
SSL_ca_file => $strCaFile);
}
or do
{
logErrorResult(ERROR_HOST_CONNECT, $EVAL_ERROR);
};
# Check for errors
if (!defined($oSocket))
{
logErrorResult(
ERROR_HOST_CONNECT, coalesce(length($!) == 0 ? undef : $!, $SSL_ERROR), length($!) > 0 ? $SSL_ERROR : undef);
}
};
# Bless with new class
$self = $class->SUPER::new(

View File

@ -5016,24 +5016,33 @@ static const EmbeddedModule embeddedModule[] =
"\n"
"my $oSocket;\n"
"\n"
"if (eval{require IO::Socket::IP})\n"
"{\n"
"$oSocket = IO::Socket::IP->new(PeerHost => $strHost, PeerPort => $iPort)\n"
"or confess &log(ERROR, \"unable to create socket: $@\", ERROR_HOST_CONNECT);\n"
"}\n"
"else\n"
"{\n"
"require IO::Socket::INET;\n"
"\n"
"$oSocket = IO::Socket::INET->new(PeerHost => $strHost, PeerPort => $iPort)\n"
"or confess &log(ERROR, \"unable to create socket: $@\", ERROR_HOST_CONNECT);\n"
"}\n"
"\n"
"setsockopt($oSocket, SOL_SOCKET,SO_KEEPALIVE, 1)\n"
"or confess &log(ERROR, \"unable to set socket keepalive: $@\", ERROR_HOST_CONNECT);\n"
"\n"
"eval\n"
"{\n"
"$oSocket = IO::Socket::SSL->new(\n"
"PeerHost => $strHost, PeerPort => $iPort, SSL_verify_mode => $bVerifySsl ? SSL_VERIFY_PEER : SSL_VERIFY_NONE,\n"
"SSL_ca_path => $strCaPath, SSL_ca_file => $strCaFile, Sockopts => [[SOL_SOCKET, SO_KEEPALIVE]]);\n"
"\n"
"return 1;\n"
"IO::Socket::SSL->start_SSL(\n"
"$oSocket, SSL_verify_mode => $bVerifySsl ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, SSL_ca_path => $strCaPath,\n"
"SSL_ca_file => $strCaFile);\n"
"}\n"
"or do\n"
"{\n"
"logErrorResult(ERROR_HOST_CONNECT, $EVAL_ERROR);\n"
"};\n"
"\n\n"
"if (!defined($oSocket))\n"
"{\n"
"logErrorResult(\n"
"ERROR_HOST_CONNECT, coalesce(length($!) == 0 ? undef : $!, $SSL_ERROR), length($!) > 0 ? $SSL_ERROR : undef);\n"
"}\n"
"};\n"
"\n\n"
"$self = $class->SUPER::new(\n"
"new pgBackRest::Common::Io::Handle('httpClient', $oSocket, $oSocket), $iProtocolTimeout, $lBufferMax);\n"

View File

@ -65,7 +65,7 @@ sub run
# this bug gets fixed by Red Hat. UPDATE: The behavior changed here but it does not seems to be fixed.
$self->testException(
sub {storageRepo({strStanza => 'test1'})->list('/')}, ERROR_HOST_CONNECT,
'IO::Socket::IP configuration failed error.*shutdown while in init',
'SSL connect attempt failed with unknown error error.*certificate verify failed',
'cert verify fails on ' . VM_CO7);
# It should work when verification is disabled
@ -104,7 +104,7 @@ sub run
$self->testException(
sub {storageRepo({strStanza => 'test4'})->list('/')}, ERROR_HOST_CONNECT,
$self->vm() eq VM_CO6 ? 'IO::Socket::INET configuration failed' : 'SSL_ca_path /bogus does not exist',
$self->vm() eq VM_CO6 ? 'SSL connect attempt failed with unknown error.*certificate verify failed' : 'No such file or directory',
'invalid ca path');
}
}