mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-08-30 12:15:12 +00:00
connection between 2 systems and bug fixes (#14)
This commit is contained in:
@@ -18,10 +18,17 @@
|
||||
#include "../interfaces/log.h"
|
||||
#include "../interfaces/repository.h"
|
||||
#include "../interfaces/com.h"
|
||||
#include "../interfaces/app.h"
|
||||
#include "../interfaces/param.h"
|
||||
#include "../interfaces/permission.h"
|
||||
#include "interface_ptr.h"
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#ifdef __GNUC__
|
||||
// Needed for getpid()
|
||||
#include <unistd.h>
|
||||
@@ -49,9 +56,11 @@ namespace sdv
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetObject(const std::string& rssObjectName)
|
||||
{
|
||||
if (!GetCore()) return nullptr;
|
||||
if (!GetCore())
|
||||
return nullptr;
|
||||
IObjectAccess* pRepository = GetCore<IObjectAccess>();
|
||||
if (!pRepository) return nullptr;
|
||||
if (!pRepository)
|
||||
return nullptr;
|
||||
return pRepository->GetObject(rssObjectName);
|
||||
}
|
||||
|
||||
@@ -63,9 +72,11 @@ namespace sdv
|
||||
*/
|
||||
inline TInterfaceAccessPtr GetObject(TObjectID tObjectID)
|
||||
{
|
||||
if (!GetCore()) return nullptr;
|
||||
if (!GetCore())
|
||||
return nullptr;
|
||||
IObjectAccess* pRepository = GetCore<IObjectAccess>();
|
||||
if (!pRepository) return nullptr;
|
||||
if (!pRepository)
|
||||
return nullptr;
|
||||
return pRepository->GetObjectByID(tObjectID);
|
||||
}
|
||||
#else
|
||||
@@ -113,21 +124,23 @@ namespace sdv
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log function enables logging for SDV.
|
||||
* @param[in] eSeverity Severity level of the log message which will be logged, e.g. Info, Warning, Error etc.
|
||||
* @param[in] rssSrcFile Name of the file from which the message is logged.
|
||||
* @param[in] uiSrcLine Line of the file from which the message is logged.
|
||||
* @param[in] rssMessage Reference to the log message to be logged.
|
||||
*/
|
||||
* @brief Log function enables logging for SDV.
|
||||
* @param[in] eSeverity Severity level of the log message which will be logged, e.g. Info, Warning, Error etc.
|
||||
* @param[in] rssSrcFile Name of the file from which the message is logged.
|
||||
* @param[in] uiSrcLine Line of the file from which the message is logged.
|
||||
* @param[in] rssMessage Reference to the log message to be logged.
|
||||
*/
|
||||
inline void Log(ELogSeverity eSeverity, const u8string& rssSrcFile, uint32_t uiSrcLine, const u8string& rssMessage)
|
||||
{
|
||||
ILogger* pLogger = GetCore() ? GetCore<ILogger>() : nullptr;
|
||||
#ifdef _WIN32
|
||||
if (pLogger) pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, _getpid(), "", rssMessage);
|
||||
if (pLogger)
|
||||
pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, _getpid(), "", rssMessage);
|
||||
#elif defined __unix__
|
||||
if (pLogger) pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, getpid(), "", rssMessage);
|
||||
if (pLogger)
|
||||
pLogger->Log(eSeverity, rssSrcFile, uiSrcLine, getpid(), "", rssMessage);
|
||||
#else
|
||||
#error The OS is currently not supported!
|
||||
#error The OS is currently not supported!
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -137,34 +150,34 @@ namespace sdv
|
||||
*/
|
||||
#define SDV_LOG(severity, ...) sdv::core::internal::CSDVLogImpl(severity, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Log a trace message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_TRACE(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::trace, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a debug message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log a debug message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_DEBUG(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::debug, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log an information message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log an information message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_INFO(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::info, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a warning message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log a warning message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_WARNING(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::warning, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log an error message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log an error message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_ERROR(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::error, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Log a fatal message with line and position.
|
||||
*/
|
||||
/**
|
||||
* @brief Log a fatal message with line and position.
|
||||
*/
|
||||
#define SDV_LOG_FATAL(...) sdv::core::internal::CSDVLogImpl(sdv::core::ELogSeverity::fatal, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
namespace internal
|
||||
@@ -176,22 +189,22 @@ namespace sdv
|
||||
* @param[in] uiSrcLine Line of the file from which the message is logged. Specified by C++ standard.
|
||||
* @param[in] ...args identifier specified by C++ standard that uses the ellipsis notation in the parameters.
|
||||
*/
|
||||
template <typename ...Args>
|
||||
inline void CSDVLogImpl(ELogSeverity eSeverity, const char* szSrcFile, uint32_t uiSrcLine, Args&& ...args)
|
||||
template <typename... Args>
|
||||
inline void CSDVLogImpl(ELogSeverity eSeverity, const char* szSrcFile, uint32_t uiSrcLine, Args&&... args)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
(stream << ... << std::forward<Args>(args));
|
||||
|
||||
Log(eSeverity, szSrcFile ? szSrcFile : "", uiSrcLine, stream.str().c_str());
|
||||
}
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* @brief Create a utility
|
||||
* @param[in] rssUtilityName Reference to the utility name.
|
||||
* @param[in] rssUtilityConfig Optional reference to the utility configuration.
|
||||
* @return Smart pointer to the utility or NULL when the utility could not be found.
|
||||
*/
|
||||
*/
|
||||
inline TObjectPtr CreateUtility(const std::string& rssUtilityName, const std::string& rssUtilityConfig = std::string())
|
||||
{
|
||||
TInterfaceAccessPtr ptrRepository = GetObject("RepositoryService");
|
||||
@@ -199,8 +212,529 @@ namespace sdv
|
||||
if (!pUtilityCreate) return nullptr;
|
||||
return pUtilityCreate->CreateUtility(rssUtilityName, rssUtilityConfig);
|
||||
}
|
||||
} // namespace core
|
||||
|
||||
/**
|
||||
* @brief Get a parameter from the object smart pointer.
|
||||
* @param[in] pParameters Pointer to the parameter map interface of an object.
|
||||
* @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
|
||||
* @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
|
||||
* found.
|
||||
* @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
|
||||
* bNoExcept was set.
|
||||
*/
|
||||
inline any_t GetParameter(const IParameters* pParameters, const std::string& rssParamName, bool bNoExcept = true)
|
||||
{
|
||||
if (!pParameters)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The object doesn't expose IParameters interface.");
|
||||
}
|
||||
any_t any = pParameters->GetParam(rssParamName);
|
||||
if (any.empty())
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The parameter could not be found.");
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a parameter from the parameter interface.
|
||||
* @param[in] rptrObject Reference to object smart pointer to the the parameter of.
|
||||
* @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
|
||||
* @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
|
||||
* found.
|
||||
* @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
|
||||
* bNoExcept was set.
|
||||
*/
|
||||
inline any_t GetParameter(const TInterfaceAccessPtr& rptrObject, const std::string& rssParamName, bool bNoExcept = true)
|
||||
{
|
||||
const IParameters* pParameters = rptrObject.GetInterface<IParameters>();
|
||||
if (!pParameters)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The object doesn't expose IParameters interface.");
|
||||
}
|
||||
return GetParameter(pParameters, rssParamName, bNoExcept);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a parameter from the object with the supplied name.
|
||||
* @param[in] rssObjectName Reference to the string containing the name of the object or service.
|
||||
* @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
|
||||
* @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
|
||||
* found.
|
||||
* @return Returns the value of the parameter or an empty any_t when the object or the parameter could not be found and
|
||||
* bNoExcept was set.
|
||||
*/
|
||||
inline any_t GetParameter(const std::string& rssObjectName, const std::string& rssParamName, bool bNoExcept = true)
|
||||
{
|
||||
TInterfaceAccessPtr ptrObject = GetObject(rssObjectName);
|
||||
if (!ptrObject)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("An object with the name '" + rssObjectName + "' could not be found.");
|
||||
}
|
||||
return GetParameter(ptrObject, rssParamName, bNoExcept);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a parameter from the object with the supplied name. Resolve enums and bitmask objects in the returned
|
||||
* parameter string.
|
||||
* @param[in] rssObjectName Reference to the string containing the name of the object or service.
|
||||
* @param[in] rssParamName Name of the parameter (incl. groups preceding the name and separated with a dot).
|
||||
* @param[in] bNoExcept When set, do not trigger an std::runtime exception when the object or the parameter could not be
|
||||
* found.
|
||||
* @return Returns the value of the parameter as a text string or an empty string when the object or the parameter could
|
||||
* not be found and bNoExcept was set.
|
||||
*/
|
||||
inline std::string GetParameterExpand(const std::string& rssObjectName, const std::string& rssParamName, bool bNoExcept = true)
|
||||
{
|
||||
TInterfaceAccessPtr ptrObject = GetObject(rssObjectName);
|
||||
if (!ptrObject)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("An object with the name '" + rssObjectName + "' could not be found.");
|
||||
}
|
||||
|
||||
const IParameters* pParameters = ptrObject.GetInterface<IParameters>();
|
||||
if (!pParameters)
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The object doesn't expose IParameters interface.");
|
||||
}
|
||||
any_t any = pParameters->GetParam(rssParamName);
|
||||
if (any.empty())
|
||||
{
|
||||
if (bNoExcept) return {};
|
||||
throw std::runtime_error("The parameter could not be found.");
|
||||
}
|
||||
|
||||
SParamInfo sParamInfo = pParameters->GetParamInfo(rssParamName);
|
||||
if (sParamInfo.get_switch() == EParamType::enum_param)
|
||||
{
|
||||
for (const SLabelInfo::SLabel& rsLabel : sParamInfo.uExtInfo.sEnumInfo.seqLabels)
|
||||
{
|
||||
if (rsLabel.anyValue == any)
|
||||
return rsLabel.ssLabel;
|
||||
}
|
||||
}
|
||||
if (sParamInfo.get_switch() == EParamType::bitmask_param)
|
||||
{
|
||||
uint64_t uiValue = static_cast<uint64_t>(any);
|
||||
std::stringstream sstreamValue;
|
||||
for (const SLabelInfo::SLabel& rsLabel : sParamInfo.uExtInfo.sBitmaskInfo.seqLabels)
|
||||
{
|
||||
uint64_t uiValueLabel = static_cast<uint64_t>(rsLabel.anyValue);
|
||||
if (uiValue & uiValueLabel)
|
||||
{
|
||||
if (sstreamValue.rdbuf()->in_avail()) // Has characters
|
||||
sstreamValue << "|";
|
||||
sstreamValue << rsLabel.ssLabel;
|
||||
uiValue = uiValue & ~uiValueLabel;
|
||||
}
|
||||
}
|
||||
if (uiValue) // Not all bits have labels
|
||||
{
|
||||
if (sstreamValue.rdbuf()->in_avail()) // Has characters
|
||||
sstreamValue << "|";
|
||||
sstreamValue << uiValue;
|
||||
}
|
||||
return sstreamValue.str();
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
/// Internal namespace
|
||||
namespace internal
|
||||
{
|
||||
/**
|
||||
* @brief Trim whitespace at the begin and end of the text.
|
||||
* @param[in] rssText Reference to the text to trim whitespace for.
|
||||
* @return The trimmed text.
|
||||
*/
|
||||
inline std::string TrimWhitespace(const std::string& rssText)
|
||||
{
|
||||
size_t nFirst = rssText.find_first_not_of(" \t\r\n");
|
||||
if (nFirst == std::string::npos) return "";
|
||||
size_t nLast = rssText.find_last_not_of(" \t\r\n");
|
||||
return rssText.substr(nFirst, (nLast - nFirst + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to safely check if a string contains a valid, unescaped $(...) sequence.
|
||||
* @param[in] rssText The text to check.
|
||||
* @return Returns whether the text represents a valid variable.
|
||||
*/
|
||||
inline bool ContainsValidVariable(const std::string& rssText)
|
||||
{
|
||||
size_t nLength = rssText.length();
|
||||
size_t nIndex = 0;
|
||||
|
||||
while (nIndex < nLength)
|
||||
{
|
||||
if (rssText[nIndex] == '\\')
|
||||
{
|
||||
// Skip the escape and the escaped character
|
||||
nIndex += 2;
|
||||
}
|
||||
else if (rssText[nIndex] == '$')
|
||||
{
|
||||
// Check if it forms the start of a token sequence '$( '
|
||||
if (nIndex + 1 < nLength && rssText[nIndex + 1] == '(')
|
||||
{
|
||||
size_t nClose = rssText.find(')', nIndex + 2);
|
||||
if (nClose != std::string::npos)
|
||||
{
|
||||
// Found a valid structural candidate
|
||||
return true;
|
||||
}
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* @brief Resolves embedded object parameter variables formatted as $(object:param) within a text string.
|
||||
* @param[in] rssText The source text containing potential variables and backslash escapes.
|
||||
* @param[in] bRecursive If true, continues resolving until no more unescaped variables remain.
|
||||
* @param[in] bNoExcept If true, returns an empty string for errors; if false, throws std::runtime_error.
|
||||
* @return The fully resolved text string.
|
||||
*/
|
||||
inline std::string ResolveText(const std::string& rssText, bool bRecursive = true, bool bNoExcept = true)
|
||||
{
|
||||
std::string ssCurrentText = rssText;
|
||||
bool bMayHaveMoreVariables = true;
|
||||
|
||||
while (bMayHaveMoreVariables)
|
||||
{
|
||||
bMayHaveMoreVariables = false;
|
||||
std::string ssResult = "";
|
||||
ssResult.reserve(ssCurrentText.length()); // Pre-allocate memory for performance
|
||||
|
||||
size_t nLength = ssCurrentText.length();
|
||||
size_t nIndex = 0;
|
||||
|
||||
while (nIndex < nLength)
|
||||
{
|
||||
char cCurrent = ssCurrentText[nIndex];
|
||||
|
||||
// Handle backslash escape sequences
|
||||
if (cCurrent == '\\')
|
||||
{
|
||||
// Check if the next character is a '$'
|
||||
if (nIndex + 1 < nLength && ssCurrentText[nIndex + 1] == '$')
|
||||
{
|
||||
ssResult.push_back('$'); // Strip the escape character, keep the literal '$'
|
||||
nIndex += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssResult.push_back('\\'); // Preserve other backslashes for paths
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
// Identify potential variables
|
||||
else if (cCurrent == '$')
|
||||
{
|
||||
// extension 2: Only throw an error or treat as a variable if it is
|
||||
// explicitly part of a dynamic sequence tracking towards a '$(...)' match.
|
||||
if (nIndex + 1 >= nLength || ssCurrentText[nIndex + 1] != '(')
|
||||
{
|
||||
// It is a loose literal '$' (like currency). Keep it and do not throw.
|
||||
ssResult.push_back('$');
|
||||
nIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t nVarStart = nIndex + 2; // Position right after "$("
|
||||
size_t nVarEnd = ssCurrentText.find(')', nVarStart);
|
||||
|
||||
// Validate that a matching closing parenthesis exists
|
||||
if (nVarEnd == std::string::npos)
|
||||
{
|
||||
if (!bNoExcept)
|
||||
throw std::runtime_error(
|
||||
"Format error: Missing closing parenthesis ')' for variable starting at index "
|
||||
+ std::to_string(nIndex));
|
||||
return "";
|
||||
}
|
||||
|
||||
// Extract the inner payload block
|
||||
std::string sVariableContent = ssCurrentText.substr(nVarStart, nVarEnd - nVarStart);
|
||||
size_t nColonPos = sVariableContent.find(':');
|
||||
|
||||
// Validate that the delimiter ':' separates object and parameter names
|
||||
if (nColonPos == std::string::npos)
|
||||
{
|
||||
if (!bNoExcept)
|
||||
throw std::runtime_error("Format error: Variable content '" + sVariableContent
|
||||
+ "' lacks an 'object:param' colon separator");
|
||||
return "";
|
||||
}
|
||||
|
||||
// Extract and clean whitespace before/after tokens, preserving inner spaces
|
||||
std::string sObjName = internal::TrimWhitespace(sVariableContent.substr(0, nColonPos));
|
||||
std::string sParamName = internal::TrimWhitespace(sVariableContent.substr(nColonPos + 1));
|
||||
|
||||
// Request the parameter.
|
||||
std::string ssValue = GetParameterExpand(sObjName, sParamName, bNoExcept);
|
||||
|
||||
// Add the parameter to the string
|
||||
ssResult.append(ssValue);
|
||||
|
||||
nIndex = nVarEnd + 1; // Move parsing index past the ')'
|
||||
}
|
||||
else
|
||||
{
|
||||
ssResult.push_back(cCurrent);
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
ssCurrentText = ssResult;
|
||||
|
||||
// Exit immediately if recursive resolution was disabled
|
||||
if (!bRecursive) break;
|
||||
|
||||
// extension 2: Intelligently analyze if a recursive processing loop is required
|
||||
if (internal::ContainsValidVariable(ssCurrentText))
|
||||
bMayHaveMoreVariables = true;
|
||||
}
|
||||
|
||||
return ssCurrentText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current access permission.
|
||||
* @return The current access permission.
|
||||
*/
|
||||
inline EAccessPermission GetCurrentAccessPermission()
|
||||
{
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl)
|
||||
return EAccessPermission::not_set;
|
||||
return pPermissionControl->GetCurrentPermission();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current transmission from this thread and prepare a transfer to another thread.
|
||||
* @return Transfer ID identifying the permission of this thread.
|
||||
*/
|
||||
inline TPermissionTransferID TransferCurrentPermission()
|
||||
{
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl) return 0u;
|
||||
return pPermissionControl->TransferCurrentPermission();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Class managing the lifetime of an access permission.
|
||||
*/
|
||||
class CAccessPermission
|
||||
{
|
||||
// Friend functions
|
||||
friend CAccessPermission RestrictAccessPermission(EAccessPermission);
|
||||
friend CAccessPermission SetAccessPermission(TPermissionTransferID);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
CAccessPermission() = default;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] tPermissionID The access permission to manage.
|
||||
*/
|
||||
CAccessPermission(TPermissionID tPermissionID) : m_tPermissionID(tPermissionID)
|
||||
{}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Copy constructor is deleted.
|
||||
* @param[in] rPermission Reference to the permission to copy from.
|
||||
*/
|
||||
CAccessPermission(const CAccessPermission& rPermission) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param[in] rPermission Reference to the permission to move from.
|
||||
*/
|
||||
CAccessPermission(CAccessPermission&& rPermission) : m_tPermissionID(rPermission.m_tPermissionID)
|
||||
{
|
||||
rPermission.m_tPermissionID = 0u;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CAccessPermission()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator is deleted.
|
||||
* @param[in] rPermission Reference to the permission to copy from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CAccessPermission& operator=(const CAccessPermission& rPermission) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
* @param[in] rPermission Reference to the permission to move from.
|
||||
* @return Reference to this class.
|
||||
*/
|
||||
CAccessPermission& operator=(CAccessPermission&& rPermission)
|
||||
{
|
||||
m_tPermissionID = rPermission.m_tPermissionID;
|
||||
rPermission.m_tPermissionID = 0u;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Boolean operator.
|
||||
* @return Returns whether a valid permission ID is assigned to this class.
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return m_tPermissionID ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Does the access permission class contain a valid permission ID.
|
||||
* @return Returns whether a valid permission ID is assigned to this class.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_tPermissionID ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release the permission.
|
||||
*/
|
||||
void Release()
|
||||
{
|
||||
if (!m_tPermissionID) return;
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl) return;
|
||||
pPermissionControl->ReleaseAccessPermission(m_tPermissionID);
|
||||
m_tPermissionID = 0u;
|
||||
}
|
||||
|
||||
private:
|
||||
TPermissionID m_tPermissionID = 0u; ///< Permission ID to be managed by this class.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Restrict the current access permission.
|
||||
* @param[in] ePermission The permission the access should be restricted to.
|
||||
* @return The access permission connected to this restriction. The lifetime of the access permission is managed by the
|
||||
* returned class.
|
||||
*/
|
||||
inline CAccessPermission RestrictAccessPermission(EAccessPermission ePermission)
|
||||
{
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl) return {};
|
||||
return pPermissionControl->RestrictAccessPermission(ePermission);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the access permission from a transfer ID that defined the access permission of a different thread.
|
||||
* @param[in] tTransferID The ID of the transferred access permission.
|
||||
* @return The access permission for the current thread. The lifetime of the access permission is managed by the returned
|
||||
* class.
|
||||
*/
|
||||
inline CAccessPermission SetAccessPermission(TPermissionTransferID tTransferID)
|
||||
{
|
||||
IPermissionControl* pPermissionControl = GetCore<IPermissionControl>();
|
||||
if (!pPermissionControl) return {};
|
||||
return pPermissionControl->SetAccessPermission(tTransferID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Secure thread implementation based on std::thread transferring the permissions from the creation thread to the
|
||||
* execution thread.
|
||||
*/
|
||||
class secure_thread : public std::thread
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
secure_thread() = default;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor is deleted.
|
||||
* @param[in] rthread Reference to the thread object.
|
||||
*/
|
||||
secure_thread(const secure_thread& rthread) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param[in] rthread Reference to the thread object.
|
||||
*/
|
||||
secure_thread(secure_thread&& rthread) : std::thread(static_cast<std::thread&&>(rthread))
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Assignment constructor for thread execution.
|
||||
* @tparam F The function to execute.
|
||||
* @tparam Args The argument types of the function to execute.
|
||||
* @param[in] f Reference to the function.
|
||||
* @param[in] args Reference to zero or more arguments.
|
||||
*/
|
||||
template <class F, class... Args>
|
||||
explicit secure_thread(F&& f, Args&&... args)
|
||||
{
|
||||
static_cast<std::thread&>(*this) = std::thread(
|
||||
[](TPermissionTransferID tTransferID, auto&& function, auto&&... arguments)
|
||||
{
|
||||
CAccessPermission permission = SetAccessPermission(tTransferID);
|
||||
std::invoke(std::forward<decltype(function)>(function), std::forward<decltype(arguments)>(arguments)...);
|
||||
}, TransferCurrentPermission(), std::forward<F>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
* @param[in] rthread Reference to the thread object.
|
||||
* @return Reference to this object.
|
||||
*/
|
||||
secure_thread& operator=(secure_thread&& rthread)
|
||||
{
|
||||
static_cast<std::thread&>(*this) = static_cast<std::thread&&>(rthread);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
} // namespace core
|
||||
}// namespace sdv
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief Comparison operators
|
||||
* @param[in] e1 First permission
|
||||
* @param[in] e2 Second permission
|
||||
* @return Result of the comparison
|
||||
*/
|
||||
inline bool operator<(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast<int32_t>(e1) < static_cast<int32_t>(e2); }
|
||||
inline bool operator<=(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast<int32_t>(e1) <= static_cast<int32_t>(e2); }
|
||||
inline bool operator>(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast<int32_t>(e1) > static_cast<int32_t>(e2); }
|
||||
inline bool operator>=(sdv::core::EAccessPermission e1, sdv::core::EAccessPermission e2) { return static_cast<int32_t>(e1) >= static_cast<int32_t>(e2); }
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
namespace sdv
|
||||
{
|
||||
namespace app
|
||||
{
|
||||
/**
|
||||
@@ -208,11 +742,11 @@ namespace sdv
|
||||
* @param[in] rssAttribute Name of the attribute.
|
||||
* @return The attribute value or an empty any-value if the attribute wasn't found or didn't have a value.
|
||||
*/
|
||||
inline any_t GetAppAttribute(const std::string& rssAttribute)
|
||||
inline any_t GetAppSettingsAttribute(const std::string& rssAttribute)
|
||||
{
|
||||
const IAttributes* ptrAppAttributes = core::GetObject<IAttributes>("AppControlService");
|
||||
if (!ptrAppAttributes) return {};
|
||||
return ptrAppAttributes->Get(rssAttribute);
|
||||
const IParameters* pParameters = core::GetObject<IParameters>("AppSettingsService");
|
||||
if (!pParameters) return {};
|
||||
return pParameters->GetParam(rssAttribute);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +755,7 @@ namespace sdv
|
||||
*/
|
||||
inline bool ConsoleIsSilent()
|
||||
{
|
||||
return GetAppAttribute("console.info_level") == "silent";
|
||||
return GetAppSettingsAttribute("Console.Reporting") == "Silent";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,7 +764,7 @@ namespace sdv
|
||||
*/
|
||||
inline bool ConsoleIsVerbose()
|
||||
{
|
||||
return GetAppAttribute("console.info_level") == "verbose";
|
||||
return GetAppSettingsAttribute("Console.Reporting") == "Verbose";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,7 +773,7 @@ namespace sdv
|
||||
*/
|
||||
inline uint32_t GetAppInstanceID()
|
||||
{
|
||||
return GetAppAttribute("app.instance_id");
|
||||
return GetAppSettingsAttribute("Application.Instance");
|
||||
}
|
||||
} // namespace app
|
||||
|
||||
@@ -247,64 +781,81 @@ namespace sdv
|
||||
{
|
||||
/**
|
||||
* @brief Create a repository connection to a local server.
|
||||
* @param[in] uiInstanceID Optionally the instance ID of the target system to connect to or 0 (default) to connect to the
|
||||
* instance identified by app-control.
|
||||
* @param[in] nRetries Number of retries to connect (optional, default 30, minimum 3).
|
||||
* @return Returns a smart pointer to the repository proxy. Disconnection takes place when IObjectDestroy::DestroyObject is
|
||||
* called.
|
||||
*/
|
||||
inline TObjectPtr ConnectToLocalServerRepository(uint32_t uiInstanceID = 0, size_t nRetries = 30)
|
||||
inline TObjectPtr ConnectToLocalServerRepository(size_t nRetries = 30)
|
||||
{
|
||||
com::IClientConnect* pClientConnect = core::GetObject<com::IClientConnect>("ConnectionService");
|
||||
if (!pClientConnect)
|
||||
// This function works with main, external and maintenance applications.
|
||||
const app::IAppContext* pAppContext = core::GetCore<app::IAppContext>();
|
||||
if (!pAppContext) return {};
|
||||
switch (pAppContext->GetContextType())
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cerr << "ERROR: Could not access the connection service." << std::endl;
|
||||
case app::EAppContext::main:
|
||||
case app::EAppContext::external:
|
||||
case app::EAppContext::maintenance:
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
const sdv::app::IAppConnections* pConnections = core::GetObject<sdv::app::IAppConnections>("AppSettingsService");
|
||||
if (!pConnections) return {};
|
||||
std::string ssConnectionConfig = pConnections->GetConnectionConfig("Default");
|
||||
if (ssConnectionConfig.empty()) return {};
|
||||
|
||||
sdv::core::IRepositoryControl* pRepository = core::GetObject<sdv::core::IRepositoryControl>("RepositoryService");
|
||||
if (!pRepository) return {};
|
||||
auto tConnectSvcID = pRepository->CreateObject("ClientConnectService", "ClientDefault", ssConnectionConfig);
|
||||
if (!tConnectSvcID) return {};
|
||||
|
||||
sdv::TInterfaceAccessPtr ptrConnectSvc = core::GetObject(tConnectSvcID);
|
||||
sdv::com::IClientConnect* pClientConnect = ptrConnectSvc.GetInterface<sdv::com::IClientConnect>();
|
||||
if (!pClientConnect)
|
||||
{
|
||||
pRepository->DestroyObject("ClientDefault");
|
||||
return {};
|
||||
}
|
||||
|
||||
// Connect the client to the server and return the server repository interface.
|
||||
std::string ssConnectString = R"code([Client]
|
||||
Type = "Local"
|
||||
)code";
|
||||
if (uiInstanceID)
|
||||
ssConnectString += "Instance = " + std::to_string(uiInstanceID) + R"code(
|
||||
)code";
|
||||
try
|
||||
{
|
||||
// Try to connect (30 times with 1 second in between).
|
||||
size_t nCnt = 0;
|
||||
sdv::TObjectPtr ptrRepository;
|
||||
while (!ptrRepository && nCnt < nRetries)
|
||||
sdv::TObjectPtr ptrRemoteRepo;
|
||||
while (!ptrRemoteRepo && nCnt < std::max(nRetries, static_cast<size_t>(3u)))
|
||||
{
|
||||
nCnt++;
|
||||
ptrRepository = pClientConnect->Connect(ssConnectString);
|
||||
if (!ptrRepository)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
if (pClientConnect->IsConnected() || pClientConnect->Connect())
|
||||
{
|
||||
ptrRemoteRepo = pClientConnect->GetRemoteRepository();
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
|
||||
// Return the result
|
||||
return ptrRepository;
|
||||
return ptrRemoteRepo;
|
||||
}
|
||||
catch (const XAccessDenied& /*rExcept*/)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Access denied trying to connect to a local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << "." << std::endl;
|
||||
app::GetAppInstanceID() << "." << std::endl;
|
||||
return {};
|
||||
}
|
||||
catch (const XNotFound& /*rExcept*/)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << " not found." << std::endl;
|
||||
app::GetAppInstanceID() << " not found." << std::endl;
|
||||
return {};
|
||||
}
|
||||
catch (const XInvalidState& rExcept)
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "The local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << " is in an invalid state: " << rExcept.what() <<
|
||||
app::GetAppInstanceID() << " is in an invalid state: " << rExcept.what() <<
|
||||
std::endl;
|
||||
return {};
|
||||
}
|
||||
@@ -312,12 +863,11 @@ Type = "Local"
|
||||
{
|
||||
if (!app::ConsoleIsSilent())
|
||||
std::cout << "Timeout occurred trying to connect to a local repository with server instance ID#" <<
|
||||
(uiInstanceID?uiInstanceID : app::GetAppInstanceID()) << "." << std::endl;
|
||||
app::GetAppInstanceID() << "." << std::endl;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace com
|
||||
} // namespace sdv
|
||||
|
||||
#endif // !defined LOCAL_SERVICE_ACCESS_H
|
||||
Reference in New Issue
Block a user