Precommit (#1)

* first commit

* cleanup
This commit is contained in:
tompzf
2025-11-04 13:28:06 +01:00
committed by GitHub
parent dba45dc636
commit 6ed4b1534e
898 changed files with 256340 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# Include cross-compilation toolchain file
include(../../cross-compile-tools.cmake)
# Define project
project(ipc_connect VERSION 1.0 LANGUAGES CXX)
# Define target
add_library(ipc_listener SHARED "listener.h" "listener.cpp")
if (WIN32)
target_link_libraries(ipc_listener ${CMAKE_THREAD_LIBS_INIT} Rpcrt4.lib)
elseif(UNIX)
target_link_libraries(ipc_listener rt ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
target_link_options(ipc_listener PRIVATE)
set_target_properties(ipc_listener PROPERTIES PREFIX "")
set_target_properties(ipc_listener PROPERTIES SUFFIX ".sdv")
# Build dependencies
add_dependencies(ipc_listener CompileCoreIDL)
# Appending the service in the service list
set(SDV_Service_List ${SDV_Service_List} ipc_listener PARENT_SCOPE)
# Define target
add_library(ipc_connect SHARED "client.h" "client.cpp")
if (WIN32)
target_link_libraries(ipc_connect ${CMAKE_THREAD_LIBS_INIT} Rpcrt4.lib)
elseif(UNIX)
target_link_libraries(ipc_connect rt ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
target_link_options(ipc_connect PRIVATE)
set_target_properties(ipc_connect PROPERTIES PREFIX "")
set_target_properties(ipc_connect PROPERTIES SUFFIX ".sdv")
# Build dependencies
add_dependencies(ipc_connect CompileCoreIDL)
# Appending the service in the service list
set(SDV_Service_List ${SDV_Service_List} ipc_connect ipc_listener PARENT_SCOPE)

View File

@@ -0,0 +1,216 @@
#include "client.h"
#include <support/toml.h>
#include <interfaces/com.h>
#include <interfaces/ipc.h>
#include <support/pssup.h>
#include <interfaces/app.h>
CRepositoryProxy::CRepositoryProxy(CClient& rClient, sdv::com::TConnectionID tConnection,
sdv::IInterfaceAccess* pRepositoryProxy) :
m_rClient(rClient), m_tConnection(tConnection), m_ptrRepositoryProxy(pRepositoryProxy)
{}
void CRepositoryProxy::DestroyObject()
{
// Call the client to disconnect the connection and destroy the object.
m_rClient.Disconnect(m_tConnection);
}
void CClient::Initialize(const sdv::u8string& /*ssObjectConfig*/)
{
m_eObjectStatus = sdv::EObjectStatus::initialized;
}
sdv::EObjectStatus CClient::GetStatus() const
{
return m_eObjectStatus;
}
void CClient::SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
void CClient::Shutdown()
{
m_eObjectStatus = sdv::EObjectStatus::shutdown_in_progress;
sdv::com::IConnectionControl* pConnectionControl = sdv::core::GetObject<sdv::com::IConnectionControl>("CommunicationControl");
if (!pConnectionControl)
SDV_LOG_ERROR("Failed to get communication control!");
// Disconnect from all repositories
std::unique_lock<std::mutex> lock(m_mtxRepositoryProxies);
auto mapRepositoryProxiesCopy = std::move(m_mapRepositoryProxies);
lock.unlock();
if (pConnectionControl)
{
for (const auto& rvtRepository : mapRepositoryProxiesCopy)
pConnectionControl->RemoveConnection(rvtRepository.first);
}
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
sdv::IInterfaceAccess* CClient::Connect(const sdv::u8string& ssConnectString)
{
const sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
if (!pContext)
{
SDV_LOG_ERROR("Failed to get application context!");
return nullptr;
}
sdv::com::IConnectionControl* pConnectionControl = sdv::core::GetObject<sdv::com::IConnectionControl>("CommunicationControl");
if (!pConnectionControl)
{
SDV_LOG_ERROR("Failed to get communication control!");
return nullptr;
}
sdv::ipc::IChannelAccess* pChannelAccess = nullptr;
std::string ssConfig;
try
{
// Determine whether the service is running as server or as client.
sdv::toml::CTOMLParser config(ssConnectString);
std::string ssType = config.GetDirect("Client.Type").GetValue();
if (ssType.empty()) ssType = "Local";
if (ssType == "Local")
{
uint32_t uiInstanceID = config.GetDirect("Client.Instance").GetValue();
pChannelAccess = sdv::core::GetObject<sdv::ipc::IChannelAccess>("LocalChannelControl");
if (!pChannelAccess)
{
SDV_LOG_ERROR("No local channel control or channel control not configured as client!");
return nullptr;
}
ssConfig = std::string(R"code([IpcChannel]
Name = "LISTENER_)code") + std::to_string(uiInstanceID ? uiInstanceID : pContext->GetInstanceID()) + R"code("
)code";
}
else if (ssType == "Remote")
{
std::string ssInterface = config.GetDirect("Client.Interface").GetValue();
uint32_t uiPort = config.GetDirect("Client.Interface").GetValue();
if (ssInterface.empty() || !uiPort)
{
SDV_LOG_ERROR("Missing interface or port number to initialize a remote client!");
return nullptr;
}
pChannelAccess = sdv::core::GetObject<sdv::ipc::IChannelAccess>("RemoteChannelControl");
if (!pChannelAccess)
{
SDV_LOG_ERROR("No remote channel control or channel control not configured as client!");
return nullptr;
}
ssConfig = R"code([IpcChannel]
Interface = ")code" + ssInterface + R"code(
Port = ")code" + std::to_string(uiPort) + R"code(
)code";
}
else
{
SDV_LOG_ERROR("Invalid or missing listener configuration for listener service!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return nullptr;
}
}
catch (const sdv::toml::XTOMLParseException& rexcept)
{
SDV_LOG_ERROR("Invalid service configuration for listener service: ", rexcept.what(), "!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return nullptr;
}
// First access the listener channel. This allows us to access the channel creation interface.
// TODO: Use named mutex to prevent multiple connections at the same time.
// Connect to the channel.
sdv::TObjectPtr ptrListenerEndpoint = pChannelAccess->Access(ssConfig);
// Assign the endpoint to the communication service.
sdv::IInterfaceAccess* pListenerProxy = nullptr;
sdv::com::TConnectionID tListenerConnection = pConnectionControl->AssignClientEndpoint(ptrListenerEndpoint, 5000,
pListenerProxy);
ptrListenerEndpoint.Clear(); // Lifetime has been taken over by communication control.
if (!tListenerConnection || !pListenerProxy)
{
SDV_LOG_ERROR("Could not assign the client endpoint!");
if (tListenerConnection != sdv::com::TConnectionID{}) pConnectionControl->RemoveConnection(tListenerConnection);
return nullptr;
}
sdv::TInterfaceAccessPtr ptrListenerProxy(pListenerProxy);
// Request for a private channel
sdv::com::IRequestChannel* pRequestChannel = ptrListenerProxy.GetInterface<sdv::com::IRequestChannel>();
if (!pRequestChannel)
{
SDV_LOG_ERROR("Could not get the channel creation interface!");
if (tListenerConnection != sdv::com::TConnectionID{}) pConnectionControl->RemoveConnection(tListenerConnection);
return nullptr;
}
sdv::u8string ssConnectionString = pRequestChannel->RequestChannel("");
// Disconnect from the listener
if (tListenerConnection != sdv::com::TConnectionID{}) pConnectionControl->RemoveConnection(tListenerConnection);
if (ssConnectionString.empty())
{
SDV_LOG_ERROR("Could not get the private channel connection information!");
return nullptr;
}
// TODO: Use named mutex to prevent multiple connections at the same time.
// Connect to the privatechannel.
sdv::TObjectPtr ptrPrivateEndpoint = pChannelAccess->Access(ssConnectionString);
// Get and return the proxy
sdv::IInterfaceAccess* pPrivateProxy = nullptr;
sdv::com::TConnectionID tPrivateConnection = pConnectionControl->AssignClientEndpoint(ptrPrivateEndpoint, 5000, pPrivateProxy);
ptrPrivateEndpoint.Clear(); // Lifetime has been taken over by communication control.
if (!tPrivateConnection || !pPrivateProxy)
{
SDV_LOG_ERROR("Could not assign the client endpoint to the private channel!");
if (tPrivateConnection != sdv::com::TConnectionID{}) pConnectionControl->RemoveConnection(tPrivateConnection);
return nullptr;
}
// Create a remote repository object
std::unique_lock<std::mutex> lock(m_mtxRepositoryProxies);
m_mapRepositoryProxies.try_emplace(tPrivateConnection, *this, tPrivateConnection, pPrivateProxy);
return pPrivateProxy;
}
void CClient::Disconnect(sdv::com::TConnectionID tConnectionID)
{
// Find the connection, disconnect and remove the connection from the repository list.
std::unique_lock<std::mutex> lock(m_mtxRepositoryProxies);
auto itRepository = m_mapRepositoryProxies.find(tConnectionID);
if (itRepository == m_mapRepositoryProxies.end()) return;
// Disconnect
sdv::com::IConnectionControl* pConnectionControl = sdv::core::GetObject<sdv::com::IConnectionControl>("CommunicationControl");
if (!pConnectionControl)
SDV_LOG_ERROR("Failed to get communication control!");
else
pConnectionControl->RemoveConnection(itRepository->first);
// Remove entry
m_mapRepositoryProxies.erase(itRepository);
}

View File

@@ -0,0 +1,133 @@
#ifndef CLIENT_H
#define CLIENT_H
#include <support/pssup.h>
#include <support/component_impl.h>
#include <interfaces/com.h>
// Forward declaration.
class CClient;
/**
* @brief Class managing the connection and providing access to the server repository through a proxy.
*/
class CRepositoryProxy : public sdv::IInterfaceAccess, public sdv::IObjectDestroy
{
public:
/**
* @brief Constructor
* @param[in] rClient Reference to the client class.
* @param[in] tConnection The connection ID to the server.
* @param[in] pRepositoryProxy Proxy to the server repository.
*/
CRepositoryProxy(CClient& rClient, sdv::com::TConnectionID tConnection, sdv::IInterfaceAccess* pRepositoryProxy);
/**
* @brief Do not allow a copy constructor.
* @param[in] rRepository Reference to the remote repository.
*/
CRepositoryProxy(const CRepositoryProxy& rRepository) = delete;
// Interface map
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectDestroy)
SDV_INTERFACE_CHAIN_MEMBER(m_ptrRepositoryProxy)
END_SDV_INTERFACE_MAP()
/**
* @brief Copy assignment is not allowed.
* @param[in] rRepository Reference to the remote repository.
*/
CRepositoryProxy& operator=(const CRepositoryProxy& rRepository) = delete;
/**
* @brief Destroy the object. Overload of sdv::IObjectDestroy::DestroyObject.
* @attention After a call of this function, all exposed interfaces render invalid and should not be used any more.
*/
virtual void DestroyObject() override;
private:
CClient& m_rClient; ///< Reference to the client object.
sdv::com::TConnectionID m_tConnection = {}; ///< Connection ID.
sdv::TInterfaceAccessPtr m_ptrRepositoryProxy; ///< Smart pointer to the remote repository.
};
/**
* @brief Client object
*/
class CClient : public sdv::CSdvObject, public sdv::IObjectControl, public sdv::com::IClientConnect
{
public:
// Interface map
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
SDV_INTERFACE_ENTRY(sdv::com::IClientConnect)
END_SDV_INTERFACE_MAP()
// Object declaration
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::SystemObject)
DECLARE_OBJECT_CLASS_NAME("ConnectionService")
DECLARE_OBJECT_SINGLETON()
/**
* @brief Initialize the object. Overload of sdv::IObjectControl::Initialize.
* @param[in] ssObjectConfig Optional configuration string.
*/
void Initialize(const sdv::u8string& ssObjectConfig) override;
/**
* @brief Get the current status of the object. Overload of sdv::IObjectControl::GetStatus.
* @return Return the current status of the object.
*/
sdv::EObjectStatus GetStatus() const override;
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode) override;
/**
* @brief Shutdown called before the object is destroyed. Overload of sdv::IObjectControl::Shutdown.
*/
void Shutdown() override;
/**
* @brief Connect to a remote system using the connection string to contact the system. Overload of
* sdv::com::IClientConnect::Connect.
* @remarks After a successful connection, the ConnectClient utility is not needed any more.
* @param[in] ssConnectString Optional connection string to use for connection. If not provided, the connection will
* automatically get the connection ID from the app-control service (default). The connection string for a local
* connection can be of the form:
* @code
* [Client]
* Type = "Local"
* Instance = 1234 # Optional: only use when connecting to a system with a different instance ID.
* @endcode
* And the following can be used for a remote connection:
* @code
* [Client]
* Type = "Remote"
* Interface = "127.0.0.1"
* Port = 2000
* @endcode
* @return Returns an interface to the repository of the remote system or a NULL pointer if not found.
*/
virtual sdv::IInterfaceAccess* Connect(const sdv::u8string& ssConnectString) override;
/**
* @brief Disconnect and remove the remote repository object.
* @param[in] tConnectionID The ID of the connection.
*/
void Disconnect(sdv::com::TConnectionID tConnectionID);
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending; ///< Object status.
std::mutex m_mtxRepositoryProxies; ///< Protect access to the remnote repository map.
std::map<sdv::com::TConnectionID, CRepositoryProxy> m_mapRepositoryProxies; ///< map of remote repositories.
};
DEFINE_SDV_OBJECT(CClient)
#endif // !defined CLIENT_H

View File

@@ -0,0 +1,218 @@
#include "listener.h"
#include <support/toml.h>
#include <interfaces/com.h>
#include <interfaces/app.h>
#include <support/pssup.h>
CChannelBroker::CChannelBroker(CListener& rListener) : m_rListener(rListener)
{}
sdv::u8string CChannelBroker::RequestChannel(/*in*/ const sdv::u8string& /*ssConfig*/)
{
// Get the communication control
sdv::com::IConnectionControl* pConnectionControl = sdv::core::GetObject<sdv::com::IConnectionControl>("CommunicationControl");
if (!pConnectionControl)
{
SDV_LOG_ERROR("Failed to get communication control!");
return {};
}
// Get the repository
sdv::TInterfaceAccessPtr ptrRespository = sdv::core::GetObject("RepositoryService");
if (!ptrRespository)
{
SDV_LOG_ERROR("Failed to get repository service!");
return {};
}
// Get the channel control.
sdv::ipc::ICreateEndpoint* pEndpoint = nullptr;
if (m_rListener.IsLocalListener())
pEndpoint = sdv::core::GetObject<sdv::ipc::ICreateEndpoint>("LocalChannelControl");
else
pEndpoint = sdv::core::GetObject<sdv::ipc::ICreateEndpoint>("RemoteChannelControl");
if (!pEndpoint)
{
SDV_LOG_ERROR("No local channel control!");
return {};
}
// Create the endpoint
sdv::ipc::SChannelEndpoint sEndpoint = pEndpoint->CreateEndpoint(sdv::u8string());
if (!sEndpoint.pConnection)
{
SDV_LOG_ERROR("Could not create the endpoint for channel request!");
return sdv::u8string();
}
sdv::TObjectPtr ptrEndpoint(sEndpoint.pConnection); // Does automatic destruction if failure happens.
// Assign the endpoint to the communication service.
sdv::com::TConnectionID tConnection = pConnectionControl->AssignServerEndpoint(ptrEndpoint, ptrRespository, 100, false);
ptrEndpoint.Clear(); // Lifetime taken over by communication control.
if (!tConnection)
{
SDV_LOG_ERROR("Could not assign the server endpoint!");
return {};
}
if (sdv::app::ConsoleIsVerbose())
std::cout << "Client connection established..." << std::endl;
// Return the connection string
return sEndpoint.ssConnectString;
}
CListener::CListener() : m_broker(*this)
{}
void CListener::Initialize(const sdv::u8string& ssObjectConfig)
{
const sdv::app::IAppContext* pContext = sdv::core::GetCore<sdv::app::IAppContext>();
if (!pContext)
{
SDV_LOG_ERROR("Failed to get application context!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
sdv::com::IConnectionControl* pConnectionControl = sdv::core::GetObject<sdv::com::IConnectionControl>("CommunicationControl");
if (!pConnectionControl)
{
SDV_LOG_ERROR("Failed to get communication control!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
sdv::ipc::ICreateEndpoint* pEndpoint = nullptr;
std::string ssConfig;
try
{
// Determine whether the service is running as server or as client.
sdv::toml::CTOMLParser config(ssObjectConfig);
std::string ssType = config.GetDirect("Listener.Type").GetValue();
if (ssType == "Local")
{
uint32_t uiInstanceID = config.GetDirect("Listener.Instance").GetValue();
m_bLocalListener = true;
pEndpoint = sdv::core::GetObject<sdv::ipc::ICreateEndpoint>("LocalChannelControl");
if (!pEndpoint)
{
SDV_LOG_ERROR("No local channel control!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
// Request the instance ID from the app control
ssConfig = std::string(R"code([IpcChannel]
Name = "LISTENER_)code") + std::to_string(uiInstanceID ? uiInstanceID : pContext->GetInstanceID()) + R"code("
Size = 2048
)code";
}
else if (ssType == "Remote")
{
m_bLocalListener = false;
std::string ssInterface = config.GetDirect("Listener.Interface").GetValue();
uint32_t uiPort = config.GetDirect("Listener.Interface").GetValue();
if (ssInterface.empty() || !uiPort)
{
SDV_LOG_ERROR("Missing interface or port number to initialize a remote listener!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
pEndpoint = sdv::core::GetObject<sdv::ipc::ICreateEndpoint>("RemoteChannelControl");
if (!pEndpoint)
{
SDV_LOG_ERROR("No remote channel control!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
ssConfig = R"code([IpcChannel]
Interface = ")code" + ssInterface + R"code(
Port = ")code" + std::to_string(uiPort) + R"code(
)code";
}
else
{
SDV_LOG_ERROR("Invalid or missing listener configuration for listener service!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
}
catch (const sdv::toml::XTOMLParseException& rexcept)
{
SDV_LOG_ERROR("Invalid service configuration for listener service: ", rexcept.what(), "!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
// Create the endpoint
sdv::ipc::SChannelEndpoint sEndpoint = pEndpoint->CreateEndpoint(ssConfig);
if (!sEndpoint.pConnection)
{
SDV_LOG_ERROR("Could not create the endpoint for listener service!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
sdv::TObjectPtr ptrEndpoint(sEndpoint.pConnection); // Does automatic destruction if failure happens.
// Assign the endpoint to the communication service.
m_tConnection = pConnectionControl->AssignServerEndpoint(ptrEndpoint, &m_broker, 100, true);
ptrEndpoint.Clear(); // Lifetime taken over by communication control.
if (!m_tConnection)
{
SDV_LOG_ERROR("Could not assign the server endpoint!");
m_eObjectStatus = sdv::EObjectStatus::initialization_failure;
return;
}
m_eObjectStatus = sdv::EObjectStatus::initialized;
}
sdv::EObjectStatus CListener::GetStatus() const
{
return m_eObjectStatus;
}
void CListener::SetOperationMode(sdv::EOperationMode eMode)
{
switch (eMode)
{
case sdv::EOperationMode::configuring:
if (m_eObjectStatus == sdv::EObjectStatus::running || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::configuring;
break;
case sdv::EOperationMode::running:
if (m_eObjectStatus == sdv::EObjectStatus::configuring || m_eObjectStatus == sdv::EObjectStatus::initialized)
m_eObjectStatus = sdv::EObjectStatus::running;
break;
default:
break;
}
}
void CListener::Shutdown()
{
m_eObjectStatus = sdv::EObjectStatus::shutdown_in_progress;
// Shutdown the listener...
if (m_tConnection != sdv::com::TConnectionID{})
{
sdv::com::IConnectionControl* pConnectionControl = sdv::core::GetObject<sdv::com::IConnectionControl>("CommunicationControl");
if (!pConnectionControl)
SDV_LOG_ERROR("Failed to get communication control; cannot shutdown gracefully!");
else
pConnectionControl->RemoveConnection(m_tConnection);
m_tConnection = {};
}
m_ptrConnection.Clear();
m_eObjectStatus = sdv::EObjectStatus::destruction_pending;
}
bool CListener::IsLocalListener() const
{
return m_bLocalListener;
}

View File

@@ -0,0 +1,113 @@
#ifndef LISTENER_H
#define LISTENER_H
#include <support/component_impl.h>
#include <interfaces/com.h>
#include <interfaces/ipc.h>
// Forward declarations
class CListener;
/**
* @brief Channel broker to request new channels. This object is exposed to the client.
*/
class CChannelBroker : public sdv::IInterfaceAccess, public sdv::com::IRequestChannel
{
public:
/**
* @brief Constructor
* @param[in] rListener Reference to the listener to forward the calls to.
*/
CChannelBroker(CListener& rListener);
// Interface map
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::com::IRequestChannel)
END_SDV_INTERFACE_MAP()
/**
* @brief Request a channel. Overload of sdv::com::IRequestChannel::RequestChannel
* @details This function creates a new endpoint and returns access to the repository through the new channel.
* @param[in] ssConfig Configuration; currently not used.
* @return The channel string needed to initialize the channel.
*/
virtual sdv::u8string RequestChannel(/*in*/ const sdv::u8string& ssConfig) override;
private:
CListener& m_rListener; ///< Reference to the listener to forward the calls to.
};
/**
* @brief Listener object
*/
class CListener : public sdv::CSdvObject, public sdv::IObjectControl
{
public:
/**
* @brief Default constructor
*/
CListener();
// Interface map
BEGIN_SDV_INTERFACE_MAP()
SDV_INTERFACE_ENTRY(sdv::IObjectControl)
END_SDV_INTERFACE_MAP()
// Object declaration
DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::SystemObject)
DECLARE_OBJECT_CLASS_NAME("ConnectionListenerService")
/**
* @brief Initialize the object. Overload of sdv::IObjectControl::Initialize.
* @details The object configuration contains the information needed to start the listener. The following configuration is
* available for the local listener:
* @code
* [Listener]
* Type = "Local"
* Instance = 1000 # Normally not used; system instance ID is used automatically.
* @endcode
* And the following is available for a remote listener:
* @code
* [Listener]
* Type = "Remote"
* Interface = "127.0.0.1"
* Port = 2000
* @endcode
* @param[in] ssObjectConfig Optional configuration string.
*/
void Initialize(const sdv::u8string& ssObjectConfig) override;
/**
* @brief Get the current status of the object. Overload of sdv::IObjectControl::GetStatus.
* @return Return the current status of the object.
*/
sdv::EObjectStatus GetStatus() const override;
/**
* @brief Set the component operation mode. Overload of sdv::IObjectControl::SetOperationMode.
* @param[in] eMode The operation mode, the component should run in.
*/
void SetOperationMode(sdv::EOperationMode eMode) override;
/**
* @brief Shutdown called before the object is destroyed. Overload of sdv::IObjectControl::Shutdown.
*/
void Shutdown() override;
/**
* @brief When set, the listener is configured to be a local listener. Otherwise the listerner is configured as remote listener.
* @return Boolean set when local lostener.
*/
bool IsLocalListener() const;
private:
sdv::EObjectStatus m_eObjectStatus = sdv::EObjectStatus::initialization_pending; ///< To update the object status when it changes.
sdv::TObjectPtr m_ptrConnection; ///< The connection object.
CChannelBroker m_broker; ///< Channel broker, used to request new channels
bool m_bLocalListener = true; ///< When set, the listener is a local listener; otherwise a remote listener.
sdv::com::TConnectionID m_tConnection = {}; ///< Channel connection ID.
};
DEFINE_SDV_OBJECT(CListener)
#endif // ! defined LISTENER_H