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> <p>The <cmd>archive-get</cmd> command is implemented entirely in C.</p>
</release-item> </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>
<release-item-contributor-list> <release-item-contributor-list>
<release-item-ideator id="james.badger"/> <release-item-ideator id="james.badger"/>
@ -6543,6 +6551,11 @@
<contributor-id type="github">mhagander</contributor-id> <contributor-id type="github">mhagander</contributor-id>
</contributor> </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 id="markus.nullmeier">
<contributor-name-display>Markus Nullmeier</contributor-name-display> <contributor-name-display>Markus Nullmeier</contributor-name-display>
<contributor-id type="github">mnullmei</contributor-id> <contributor-id type="github">mnullmei</contributor-id>

View File

@ -97,25 +97,33 @@ sub new
# Connect to the server # Connect to the server
my $oSocket; 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 eval
{ {
$oSocket = IO::Socket::SSL->new( IO::Socket::SSL->start_SSL(
PeerHost => $strHost, PeerPort => $iPort, SSL_verify_mode => $bVerifySsl ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, $oSocket, SSL_verify_mode => $bVerifySsl ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, SSL_ca_path => $strCaPath,
SSL_ca_path => $strCaPath, SSL_ca_file => $strCaFile, Sockopts => [[SOL_SOCKET, SO_KEEPALIVE]]); SSL_ca_file => $strCaFile);
return 1;
} }
or do or do
{
logErrorResult(ERROR_HOST_CONNECT, $EVAL_ERROR);
};
# Check for errors
if (!defined($oSocket))
{ {
logErrorResult( logErrorResult(
ERROR_HOST_CONNECT, coalesce(length($!) == 0 ? undef : $!, $SSL_ERROR), length($!) > 0 ? $SSL_ERROR : undef); ERROR_HOST_CONNECT, coalesce(length($!) == 0 ? undef : $!, $SSL_ERROR), length($!) > 0 ? $SSL_ERROR : undef);
} };
# Bless with new class # Bless with new class
$self = $class->SUPER::new( $self = $class->SUPER::new(

View File

@ -5016,24 +5016,33 @@ static const EmbeddedModule embeddedModule[] =
"\n" "\n"
"my $oSocket;\n" "my $oSocket;\n"
"\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" "eval\n"
"{\n" "{\n"
"$oSocket = IO::Socket::SSL->new(\n" "IO::Socket::SSL->start_SSL(\n"
"PeerHost => $strHost, PeerPort => $iPort, SSL_verify_mode => $bVerifySsl ? SSL_VERIFY_PEER : SSL_VERIFY_NONE,\n" "$oSocket, SSL_verify_mode => $bVerifySsl ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, SSL_ca_path => $strCaPath,\n"
"SSL_ca_path => $strCaPath, SSL_ca_file => $strCaFile, Sockopts => [[SOL_SOCKET, SO_KEEPALIVE]]);\n" "SSL_ca_file => $strCaFile);\n"
"\n"
"return 1;\n"
"}\n" "}\n"
"or do\n" "or do\n"
"{\n" "{\n"
"logErrorResult(ERROR_HOST_CONNECT, $EVAL_ERROR);\n"
"};\n"
"\n\n"
"if (!defined($oSocket))\n"
"{\n"
"logErrorResult(\n" "logErrorResult(\n"
"ERROR_HOST_CONNECT, coalesce(length($!) == 0 ? undef : $!, $SSL_ERROR), length($!) > 0 ? $SSL_ERROR : undef);\n" "ERROR_HOST_CONNECT, coalesce(length($!) == 0 ? undef : $!, $SSL_ERROR), length($!) > 0 ? $SSL_ERROR : undef);\n"
"}\n" "};\n"
"\n\n" "\n\n"
"$self = $class->SUPER::new(\n" "$self = $class->SUPER::new(\n"
"new pgBackRest::Common::Io::Handle('httpClient', $oSocket, $oSocket), $iProtocolTimeout, $lBufferMax);\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. # this bug gets fixed by Red Hat. UPDATE: The behavior changed here but it does not seems to be fixed.
$self->testException( $self->testException(
sub {storageRepo({strStanza => 'test1'})->list('/')}, ERROR_HOST_CONNECT, 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); 'cert verify fails on ' . VM_CO7);
# It should work when verification is disabled # It should work when verification is disabled
@ -104,7 +104,7 @@ sub run
$self->testException( $self->testException(
sub {storageRepo({strStanza => 'test4'})->list('/')}, ERROR_HOST_CONNECT, 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'); 'invalid ca path');
} }
} }