mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Fix leaks in protocol module.
These leaks were not a big deal individually and there are generally few protocol objects created, but the leaks ended up in mem contexts that persist for most of execution. It makes sense to keep long-lived contexts as tidy as possible.
This commit is contained in:
parent
78e912a932
commit
a56fa0eb45
@ -171,7 +171,11 @@ protocolLocalParam(ProtocolStorageType protocolStorageType, unsigned int hostIdx
|
||||
// Disable output to stdout since it is used by the protocol
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOG_LEVEL_CONSOLE), VARSTRDEF("off"));
|
||||
|
||||
result = strLstMove(cfgExecParam(cfgCommand(), cfgCmdRoleLocal, optionReplace, true, false), memContextPrior());
|
||||
MEM_CONTEXT_PRIOR_BEGIN()
|
||||
{
|
||||
result = cfgExecParam(cfgCommand(), cfgCmdRoleLocal, optionReplace, true, false);
|
||||
}
|
||||
MEM_CONTEXT_PRIOR_END();
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
@ -193,19 +197,34 @@ protocolLocalExec(
|
||||
|
||||
ASSERT(helper != NULL);
|
||||
|
||||
// Execute the protocol command
|
||||
helper->exec = execNew(
|
||||
cfgExe(), protocolLocalParam(protocolStorageType, hostIdx, processId),
|
||||
strNewFmt(PROTOCOL_SERVICE_LOCAL "-%u process", processId), cfgOptionUInt64(cfgOptProtocolTimeout));
|
||||
execOpen(helper->exec);
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Execute the protocol command
|
||||
const String *name = strNewFmt(PROTOCOL_SERVICE_LOCAL "-%u process", processId);
|
||||
const StringList *const param = protocolLocalParam(protocolStorageType, hostIdx, processId);
|
||||
|
||||
// Create protocol object
|
||||
helper->client = protocolClientNew(
|
||||
strNewFmt(PROTOCOL_SERVICE_LOCAL "-%u protocol", processId),
|
||||
PROTOCOL_SERVICE_LOCAL_STR, execIoRead(helper->exec), execIoWrite(helper->exec));
|
||||
MEM_CONTEXT_PRIOR_BEGIN()
|
||||
{
|
||||
helper->exec = execNew(cfgExe(), param, name, cfgOptionUInt64(cfgOptProtocolTimeout));
|
||||
}
|
||||
MEM_CONTEXT_PRIOR_END();
|
||||
|
||||
// Move client to exec context so they are freed together
|
||||
protocolClientMove(helper->client, execMemContext(helper->exec));
|
||||
execOpen(helper->exec);
|
||||
|
||||
// Create protocol object
|
||||
name = strNewFmt(PROTOCOL_SERVICE_LOCAL "-%u protocol", processId);
|
||||
|
||||
MEM_CONTEXT_PRIOR_BEGIN()
|
||||
{
|
||||
helper->client = protocolClientNew(
|
||||
name, PROTOCOL_SERVICE_LOCAL_STR, execIoRead(helper->exec), execIoWrite(helper->exec));
|
||||
}
|
||||
MEM_CONTEXT_PRIOR_END();
|
||||
|
||||
// Move client to exec context so they are freed together
|
||||
protocolClientMove(helper->client, execMemContext(helper->exec));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
@ -332,29 +351,39 @@ protocolServerAuthorize(const String *authListStr, const String *const stanza)
|
||||
|
||||
ASSERT(authListStr != NULL);
|
||||
|
||||
// Empty list is not valid. ??? It would be better if this were done during config parsing.
|
||||
authListStr = strTrim(strDup(authListStr));
|
||||
bool result = false;
|
||||
|
||||
if (strEmpty(authListStr))
|
||||
THROW(OptionInvalidValueError, "'" CFGOPT_TLS_SERVER_AUTH "' option must have a value");
|
||||
|
||||
// If * then all stanzas are authorized
|
||||
if (strEqZ(authListStr, "*"))
|
||||
FUNCTION_TEST_RETURN(BOOL, true);
|
||||
|
||||
// Check the list of stanzas for a match with the specified stanza. Each entry will need to be trimmed before comparing.
|
||||
if (stanza != NULL)
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
StringList *authList = strLstNewSplitZ(authListStr, COMMA_Z);
|
||||
// Empty list is not valid. ??? It would be better if this were done during config parsing.
|
||||
authListStr = strTrim(strDup(authListStr));
|
||||
|
||||
for (unsigned int authListIdx = 0; authListIdx < strLstSize(authList); authListIdx++)
|
||||
if (strEmpty(authListStr))
|
||||
THROW(OptionInvalidValueError, "'" CFGOPT_TLS_SERVER_AUTH "' option must have a value");
|
||||
|
||||
// If * then all stanzas are authorized
|
||||
if (strEqZ(authListStr, "*"))
|
||||
{
|
||||
if (strEq(strTrim(strLstGet(authList, authListIdx)), stanza))
|
||||
FUNCTION_TEST_RETURN(BOOL, true);
|
||||
result = true;
|
||||
}
|
||||
// Else check the stanza list for a match with the specified stanza. Each entry will need to be trimmed before comparing.
|
||||
else if (stanza != NULL)
|
||||
{
|
||||
StringList *authList = strLstNewSplitZ(authListStr, COMMA_Z);
|
||||
|
||||
for (unsigned int authListIdx = 0; authListIdx < strLstSize(authList); authListIdx++)
|
||||
{
|
||||
if (strEq(strTrim(strLstGet(authList, authListIdx)), stanza))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN(BOOL, false);
|
||||
FUNCTION_TEST_RETURN(BOOL, result);
|
||||
}
|
||||
|
||||
ProtocolServer *
|
||||
@ -443,127 +472,139 @@ protocolRemoteParam(ProtocolStorageType protocolStorageType, unsigned int hostId
|
||||
FUNCTION_LOG_PARAM(UINT, hostIdx);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
// Is this a repo remote?
|
||||
bool isRepo = protocolStorageType == protocolStorageTypeRepo;
|
||||
StringList *result = NULL;
|
||||
|
||||
// Option replacements
|
||||
KeyValue *optionReplace = kvNew();
|
||||
|
||||
// Replace config options with the host versions
|
||||
unsigned int optConfig = isRepo ? cfgOptRepoHostConfig : cfgOptPgHostConfig;
|
||||
|
||||
kvPut(
|
||||
optionReplace, VARSTRDEF(CFGOPT_CONFIG),
|
||||
cfgOptionIdxSource(optConfig, hostIdx) != cfgSourceDefault ? VARSTR(cfgOptionIdxStr(optConfig, hostIdx)) : NULL);
|
||||
|
||||
unsigned int optConfigIncludePath = isRepo ? cfgOptRepoHostConfigIncludePath : cfgOptPgHostConfigIncludePath;
|
||||
|
||||
kvPut(
|
||||
optionReplace, VARSTRDEF(CFGOPT_CONFIG_INCLUDE_PATH),
|
||||
cfgOptionIdxSource(optConfigIncludePath, hostIdx) != cfgSourceDefault ?
|
||||
VARSTR(cfgOptionIdxStr(optConfigIncludePath, hostIdx)) : NULL);
|
||||
|
||||
unsigned int optConfigPath = isRepo ? cfgOptRepoHostConfigPath : cfgOptPgHostConfigPath;
|
||||
|
||||
kvPut(
|
||||
optionReplace, VARSTRDEF(CFGOPT_CONFIG_PATH),
|
||||
cfgOptionIdxSource(optConfigPath, hostIdx) != cfgSourceDefault ? VARSTR(cfgOptionIdxStr(optConfigPath, hostIdx)) : NULL);
|
||||
|
||||
// Update/remove repo/pg options that are sent to the remote
|
||||
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Skip options that are not part of a group
|
||||
if (!cfgOptionGroup(optionId))
|
||||
continue;
|
||||
// Is this a repo remote?
|
||||
bool isRepo = protocolStorageType == protocolStorageTypeRepo;
|
||||
|
||||
bool remove = false;
|
||||
bool skipHostZero = false;
|
||||
// Option replacements
|
||||
KeyValue *optionReplace = kvNew();
|
||||
|
||||
// Remove repo options that are not needed on the remote
|
||||
if (cfgOptionGroupId(optionId) == cfgOptGrpRepo)
|
||||
// Replace config options with the host versions
|
||||
unsigned int optConfig = isRepo ? cfgOptRepoHostConfig : cfgOptPgHostConfig;
|
||||
|
||||
kvPut(
|
||||
optionReplace, VARSTRDEF(CFGOPT_CONFIG),
|
||||
cfgOptionIdxSource(optConfig, hostIdx) != cfgSourceDefault ? VARSTR(cfgOptionIdxStr(optConfig, hostIdx)) : NULL);
|
||||
|
||||
unsigned int optConfigIncludePath = isRepo ? cfgOptRepoHostConfigIncludePath : cfgOptPgHostConfigIncludePath;
|
||||
|
||||
kvPut(
|
||||
optionReplace, VARSTRDEF(CFGOPT_CONFIG_INCLUDE_PATH),
|
||||
cfgOptionIdxSource(optConfigIncludePath, hostIdx) != cfgSourceDefault ?
|
||||
VARSTR(cfgOptionIdxStr(optConfigIncludePath, hostIdx)) : NULL);
|
||||
|
||||
unsigned int optConfigPath = isRepo ? cfgOptRepoHostConfigPath : cfgOptPgHostConfigPath;
|
||||
|
||||
kvPut(
|
||||
optionReplace, VARSTRDEF(CFGOPT_CONFIG_PATH),
|
||||
cfgOptionIdxSource(optConfigPath, hostIdx) != cfgSourceDefault ? VARSTR(cfgOptionIdxStr(optConfigPath, hostIdx)) : NULL);
|
||||
|
||||
// Update/remove repo/pg options that are sent to the remote
|
||||
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
|
||||
{
|
||||
// If remote type is pg then remove all repo options since they will not be used
|
||||
if (protocolStorageType == protocolStorageTypePg)
|
||||
// Skip options that are not part of a group
|
||||
if (!cfgOptionGroup(optionId))
|
||||
continue;
|
||||
|
||||
bool remove = false;
|
||||
bool skipHostZero = false;
|
||||
|
||||
// Remove repo options that are not needed on the remote
|
||||
if (cfgOptionGroupId(optionId) == cfgOptGrpRepo)
|
||||
{
|
||||
remove = true;
|
||||
// If remote type is pg then remove all repo options since they will not be used
|
||||
if (protocolStorageType == protocolStorageTypePg)
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
// Else remove repo options for indexes that are not being passed to the repo. This prevents the remote from getting
|
||||
// partial info about a repo, which could cause an error during validation.
|
||||
else
|
||||
{
|
||||
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIdxTotal(optionId); optionIdx++)
|
||||
{
|
||||
if (cfgOptionIdxTest(optionId, optionIdx) && optionIdx != hostIdx)
|
||||
kvPut(optionReplace, VARSTRZ(cfgOptionIdxName(optionId, optionIdx)), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else remove repo options for indexes that are not being passed to the repo. This prevents the remote from getting
|
||||
// partial info about a repo, which could cause an error during validation.
|
||||
// Remove pg options that are not needed on the remote
|
||||
else
|
||||
{
|
||||
ASSERT(cfgOptionGroupId(optionId) == cfgOptGrpPg);
|
||||
|
||||
// Remove unrequired/defaulted pg options when the remote type is repo since they won't be used
|
||||
if (protocolStorageType == protocolStorageTypeRepo)
|
||||
{
|
||||
remove = !cfgParseOptionRequired(cfgCommand(), optionId) || cfgParseOptionDefault(cfgCommand(), optionId) != NULL;
|
||||
}
|
||||
// Move pg options to host index 0 (key 1) so they will be in the default index on the remote host
|
||||
else
|
||||
{
|
||||
if (hostIdx != 0)
|
||||
{
|
||||
kvPut(
|
||||
optionReplace, VARSTRZ(cfgOptionIdxName(optionId, 0)),
|
||||
cfgOptionIdxSource(optionId, hostIdx) != cfgSourceDefault ? cfgOptionIdxVar(optionId, hostIdx) : NULL);
|
||||
}
|
||||
|
||||
remove = true;
|
||||
skipHostZero = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove options that have been marked for removal if they are not already null or invalid. This is more efficient because
|
||||
// cfgExecParam() won't have to search through as large a list looking for overrides.
|
||||
if (remove)
|
||||
{
|
||||
// Loop through option indexes
|
||||
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIdxTotal(optionId); optionIdx++)
|
||||
{
|
||||
if (cfgOptionIdxTest(optionId, optionIdx) && optionIdx != hostIdx)
|
||||
if (cfgOptionIdxTest(optionId, optionIdx) && !(skipHostZero && optionIdx == 0))
|
||||
kvPut(optionReplace, VARSTRZ(cfgOptionIdxName(optionId, optionIdx)), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove pg options that are not needed on the remote
|
||||
else
|
||||
|
||||
// Set repo default so the remote only operates on a single repo
|
||||
if (protocolStorageType == protocolStorageTypeRepo)
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_REPO), VARUINT(cfgOptionGroupIdxToKey(cfgOptGrpRepo, hostIdx)));
|
||||
|
||||
// Add the process id if not set. This means that the remote is being started from the main process and should always get a
|
||||
// process id of 0.
|
||||
if (!cfgOptionTest(cfgOptProcess))
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_PROCESS), VARINT(0));
|
||||
|
||||
// Don't pass log-path or lock-path since these are host specific
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOG_PATH), NULL);
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOCK_PATH), NULL);
|
||||
|
||||
// Only enable file logging on the remote when requested
|
||||
kvPut(
|
||||
optionReplace, VARSTRDEF(CFGOPT_LOG_LEVEL_FILE),
|
||||
cfgOptionBool(cfgOptLogSubprocess) ? VARUINT64(cfgOptionStrId(cfgOptLogLevelFile)) : VARSTRDEF("off"));
|
||||
|
||||
// Always output errors on stderr for debugging purposes
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOG_LEVEL_STDERR), VARSTRDEF("error"));
|
||||
|
||||
// Disable output to stdout since it is used by the protocol
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOG_LEVEL_CONSOLE), VARSTRDEF("off"));
|
||||
|
||||
// Add the remote type
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_REMOTE_TYPE), VARSTR(strIdToStr(protocolStorageType)));
|
||||
|
||||
MEM_CONTEXT_PRIOR_BEGIN()
|
||||
{
|
||||
ASSERT(cfgOptionGroupId(optionId) == cfgOptGrpPg);
|
||||
|
||||
// Remove unrequired/defaulted pg options when the remote type is repo since they won't be used
|
||||
if (protocolStorageType == protocolStorageTypeRepo)
|
||||
{
|
||||
remove = !cfgParseOptionRequired(cfgCommand(), optionId) || cfgParseOptionDefault(cfgCommand(), optionId) != NULL;
|
||||
}
|
||||
// Move pg options to host index 0 (key 1) so they will be in the default index on the remote host
|
||||
else
|
||||
{
|
||||
if (hostIdx != 0)
|
||||
{
|
||||
kvPut(
|
||||
optionReplace, VARSTRZ(cfgOptionIdxName(optionId, 0)),
|
||||
cfgOptionIdxSource(optionId, hostIdx) != cfgSourceDefault ? cfgOptionIdxVar(optionId, hostIdx) : NULL);
|
||||
}
|
||||
|
||||
remove = true;
|
||||
skipHostZero = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove options that have been marked for removal if they are not already null or invalid. This is more efficient because
|
||||
// cfgExecParam() won't have to search through as large a list looking for overrides.
|
||||
if (remove)
|
||||
{
|
||||
// Loop through option indexes
|
||||
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIdxTotal(optionId); optionIdx++)
|
||||
{
|
||||
if (cfgOptionIdxTest(optionId, optionIdx) && !(skipHostZero && optionIdx == 0))
|
||||
kvPut(optionReplace, VARSTRZ(cfgOptionIdxName(optionId, optionIdx)), NULL);
|
||||
}
|
||||
result = cfgExecParam(cfgCommand(), cfgCmdRoleRemote, optionReplace, false, true);
|
||||
}
|
||||
MEM_CONTEXT_PRIOR_END();
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
// Set repo default so the remote only operates on a single repo
|
||||
if (protocolStorageType == protocolStorageTypeRepo)
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_REPO), VARUINT(cfgOptionGroupIdxToKey(cfgOptGrpRepo, hostIdx)));
|
||||
|
||||
// Add the process id if not set. This means that the remote is being started from the main process and should always get a
|
||||
// process id of 0.
|
||||
if (!cfgOptionTest(cfgOptProcess))
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_PROCESS), VARINT(0));
|
||||
|
||||
// Don't pass log-path or lock-path since these are host specific
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOG_PATH), NULL);
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOCK_PATH), NULL);
|
||||
|
||||
// Only enable file logging on the remote when requested
|
||||
kvPut(
|
||||
optionReplace, VARSTRDEF(CFGOPT_LOG_LEVEL_FILE),
|
||||
cfgOptionBool(cfgOptLogSubprocess) ? VARUINT64(cfgOptionStrId(cfgOptLogLevelFile)) : VARSTRDEF("off"));
|
||||
|
||||
// Always output errors on stderr for debugging purposes
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOG_LEVEL_STDERR), VARSTRDEF("error"));
|
||||
|
||||
// Disable output to stdout since it is used by the protocol
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_LOG_LEVEL_CONSOLE), VARSTRDEF("off"));
|
||||
|
||||
// Add the remote type
|
||||
kvPut(optionReplace, VARSTRDEF(CFGOPT_REMOTE_TYPE), VARSTR(strIdToStr(protocolStorageType)));
|
||||
|
||||
FUNCTION_LOG_RETURN(STRING_LIST, cfgExecParam(cfgCommand(), cfgCmdRoleRemote, optionReplace, false, true));
|
||||
FUNCTION_LOG_RETURN(STRING_LIST, result);
|
||||
}
|
||||
|
||||
// Helper to add SSH parameters when executing the remote via SSH
|
||||
@ -575,7 +616,7 @@ protocolRemoteParamSsh(const ProtocolStorageType protocolStorageType, const unsi
|
||||
FUNCTION_LOG_PARAM(UINT, hostIdx);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
StringList *result = NULL;
|
||||
StringList *result = strLstNew();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
@ -583,7 +624,6 @@ protocolRemoteParamSsh(const ProtocolStorageType protocolStorageType, const unsi
|
||||
bool isRepo = protocolStorageType == protocolStorageTypeRepo;
|
||||
|
||||
// Fixed parameters for ssh command
|
||||
result = strLstNew();
|
||||
strLstAddZ(result, "-o");
|
||||
strLstAddZ(result, "LogLevel=error");
|
||||
strLstAddZ(result, "-o");
|
||||
@ -610,9 +650,6 @@ protocolRemoteParamSsh(const ProtocolStorageType protocolStorageType, const unsi
|
||||
|
||||
strLstInsert(paramList, 0, cfgOptionIdxStr(isRepo ? cfgOptRepoHostCmd : cfgOptPgHostCmd, hostIdx));
|
||||
strLstAdd(result, strLstJoin(paramList, " "));
|
||||
|
||||
// Move to prior context
|
||||
strLstMove(result, memContextPrior());
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
@ -635,84 +672,104 @@ protocolRemoteExec(
|
||||
|
||||
ASSERT(helper != NULL);
|
||||
|
||||
// Get remote info
|
||||
const bool isRepo = protocolStorageType == protocolStorageTypeRepo;
|
||||
const StringId remoteType = cfgOptionIdxStrId(isRepo ? cfgOptRepoHostType : cfgOptPgHostType, hostIdx);
|
||||
const String *const host = cfgOptionIdxStr(isRepo ? cfgOptRepoHost : cfgOptPgHost, hostIdx);
|
||||
|
||||
// Handle remote types
|
||||
IoRead *read;
|
||||
IoWrite *write;
|
||||
|
||||
switch (remoteType)
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// SSH remote
|
||||
case CFGOPTVAL_REPO_HOST_TYPE_SSH:
|
||||
// Get remote info
|
||||
const bool isRepo = protocolStorageType == protocolStorageTypeRepo;
|
||||
const StringId remoteType = cfgOptionIdxStrId(isRepo ? cfgOptRepoHostType : cfgOptPgHostType, hostIdx);
|
||||
const String *const host = cfgOptionIdxStr(isRepo ? cfgOptRepoHost : cfgOptPgHost, hostIdx);
|
||||
|
||||
// Handle remote types
|
||||
IoRead *read;
|
||||
IoWrite *write;
|
||||
|
||||
switch (remoteType)
|
||||
{
|
||||
// Exec SSH
|
||||
helper->exec = execNew(
|
||||
cfgOptionStr(cfgOptCmdSsh), protocolRemoteParamSsh(protocolStorageType, hostIdx),
|
||||
strNewFmt(PROTOCOL_SERVICE_REMOTE "-%u process on '%s'", processId, strZ(host)),
|
||||
cfgOptionUInt64(cfgOptProtocolTimeout));
|
||||
execOpen(helper->exec);
|
||||
// SSH remote
|
||||
case CFGOPTVAL_REPO_HOST_TYPE_SSH:
|
||||
{
|
||||
// Exec SSH
|
||||
const String *const name = strNewFmt(PROTOCOL_SERVICE_REMOTE "-%u process on '%s'", processId, strZ(host));
|
||||
const StringList *const param = protocolRemoteParamSsh(protocolStorageType, hostIdx);
|
||||
|
||||
read = execIoRead(helper->exec);
|
||||
write = execIoWrite(helper->exec);
|
||||
MEM_CONTEXT_PRIOR_BEGIN()
|
||||
{
|
||||
helper->exec = execNew(cfgOptionStr(cfgOptCmdSsh), param, name, cfgOptionUInt64(cfgOptProtocolTimeout));
|
||||
}
|
||||
MEM_CONTEXT_PRIOR_END();
|
||||
|
||||
break;
|
||||
execOpen(helper->exec);
|
||||
|
||||
read = execIoRead(helper->exec);
|
||||
write = execIoWrite(helper->exec);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// TLS remote
|
||||
default:
|
||||
{
|
||||
ASSERT(remoteType == CFGOPTVAL_REPO_HOST_TYPE_TLS);
|
||||
|
||||
// Negotiate TLS
|
||||
MEM_CONTEXT_PRIOR_BEGIN()
|
||||
{
|
||||
helper->ioClient = tlsClientNewP(
|
||||
sckClientNew(
|
||||
host, cfgOptionIdxUInt(isRepo ? cfgOptRepoHostPort : cfgOptPgHostPort, hostIdx),
|
||||
cfgOptionUInt64(cfgOptIoTimeout), cfgOptionUInt64(cfgOptProtocolTimeout)),
|
||||
host, cfgOptionUInt64(cfgOptIoTimeout), cfgOptionUInt64(cfgOptProtocolTimeout), true,
|
||||
.caFile = cfgOptionIdxStrNull(isRepo ? cfgOptRepoHostCaFile : cfgOptPgHostCaFile, hostIdx),
|
||||
.caPath = cfgOptionIdxStrNull(isRepo ? cfgOptRepoHostCaPath : cfgOptPgHostCaPath, hostIdx),
|
||||
.certFile = cfgOptionIdxStr(isRepo ? cfgOptRepoHostCertFile : cfgOptPgHostCertFile, hostIdx),
|
||||
.keyFile = cfgOptionIdxStr(isRepo ? cfgOptRepoHostKeyFile : cfgOptPgHostKeyFile, hostIdx));
|
||||
|
||||
helper->ioSession = ioClientOpen(helper->ioClient);
|
||||
}
|
||||
MEM_CONTEXT_PRIOR_END();
|
||||
|
||||
read = ioSessionIoReadP(helper->ioSession);
|
||||
write = ioSessionIoWrite(helper->ioSession);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TLS remote
|
||||
default:
|
||||
// Create protocol object
|
||||
const String *const name = strNewFmt(
|
||||
PROTOCOL_SERVICE_REMOTE "-%u %s protocol on '%s'", processId, strZ(strIdToStr(remoteType)), strZ(host));
|
||||
|
||||
MEM_CONTEXT_PRIOR_BEGIN()
|
||||
{
|
||||
ASSERT(remoteType == CFGOPTVAL_REPO_HOST_TYPE_TLS);
|
||||
helper->client = protocolClientNew(name, PROTOCOL_SERVICE_REMOTE_STR, read, write);
|
||||
}
|
||||
MEM_CONTEXT_PRIOR_END();
|
||||
|
||||
// Negotiate TLS
|
||||
helper->ioClient = tlsClientNewP(
|
||||
sckClientNew(
|
||||
host, cfgOptionIdxUInt(isRepo ? cfgOptRepoHostPort : cfgOptPgHostPort, hostIdx),
|
||||
cfgOptionUInt64(cfgOptIoTimeout), cfgOptionUInt64(cfgOptProtocolTimeout)),
|
||||
host, cfgOptionUInt64(cfgOptIoTimeout), cfgOptionUInt64(cfgOptProtocolTimeout), true,
|
||||
.caFile = cfgOptionIdxStrNull(isRepo ? cfgOptRepoHostCaFile : cfgOptPgHostCaFile, hostIdx),
|
||||
.caPath = cfgOptionIdxStrNull(isRepo ? cfgOptRepoHostCaPath : cfgOptPgHostCaPath, hostIdx),
|
||||
.certFile = cfgOptionIdxStr(isRepo ? cfgOptRepoHostCertFile : cfgOptPgHostCertFile, hostIdx),
|
||||
.keyFile = cfgOptionIdxStr(isRepo ? cfgOptRepoHostKeyFile : cfgOptPgHostKeyFile, hostIdx));
|
||||
helper->ioSession = ioClientOpen(helper->ioClient);
|
||||
// Remote initialization
|
||||
switch (remoteType)
|
||||
{
|
||||
// SSH remote
|
||||
case CFGOPTVAL_REPO_HOST_TYPE_SSH:
|
||||
// Move client to exec context so they are freed together
|
||||
protocolClientMove(helper->client, execMemContext(helper->exec));
|
||||
break;
|
||||
|
||||
read = ioSessionIoReadP(helper->ioSession);
|
||||
write = ioSessionIoWrite(helper->ioSession);
|
||||
// TLS remote
|
||||
default:
|
||||
{
|
||||
ASSERT(remoteType == CFGOPTVAL_REPO_HOST_TYPE_TLS);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create protocol object
|
||||
helper->client = protocolClientNew(
|
||||
strNewFmt(PROTOCOL_SERVICE_REMOTE "-%u %s protocol on '%s'", processId, strZ(strIdToStr(remoteType)), strZ(host)),
|
||||
PROTOCOL_SERVICE_REMOTE_STR, read, write);
|
||||
|
||||
// Remote initialization
|
||||
switch (remoteType)
|
||||
{
|
||||
// SSH remote
|
||||
case CFGOPTVAL_REPO_HOST_TYPE_SSH:
|
||||
// Move client to exec context so they are freed together
|
||||
protocolClientMove(helper->client, execMemContext(helper->exec));
|
||||
break;
|
||||
|
||||
// TLS remote
|
||||
default:
|
||||
{
|
||||
ASSERT(remoteType == CFGOPTVAL_REPO_HOST_TYPE_TLS);
|
||||
|
||||
// Pass parameters to server
|
||||
ProtocolCommand *command = protocolCommandNew(PROTOCOL_COMMAND_CONFIG);
|
||||
pckWriteStrLstP(protocolCommandParam(command), protocolRemoteParam(protocolStorageType, hostIdx));
|
||||
protocolClientExecute(helper->client, command, false);
|
||||
|
||||
break;
|
||||
// Pass parameters to server
|
||||
ProtocolCommand *const command = protocolCommandNew(PROTOCOL_COMMAND_CONFIG);
|
||||
pckWriteStrLstP(protocolCommandParam(command), protocolRemoteParam(protocolStorageType, hostIdx));
|
||||
protocolClientExecute(helper->client, command, false);
|
||||
protocolCommandFree(command);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user