/******************************************************************************** * Copyright (c) 2025-2026 ZF Friedrichshafen AG * * This program and the accompanying materials are made available under the * terms of the Apache License Version 2.0 which is available at * https://www.apache.org/licenses/LICENSE-2.0 * * SPDX-License-Identifier: Apache-2.0 * * Contributors: * Erik Verhoeven - initial API and implementation ********************************************************************************/ #ifndef COM_CTRL_H #define COM_CTRL_H #include #include #include // Forward declaration class CChannelConnector; class CMarshallObject; /** * @brief Test object simulating an component isolation service implementation for channel implementation testing */ class CCommunicationControl : public sdv::CSdvObject, public sdv::com::IConnectionControl, public sdv::ps::IMarshallAccess { public: /** * @brief Constructor. */ CCommunicationControl(); /** * @brief Destructor added to cleanly stop service in case process is stopped (without shutdown via repository service) */ virtual ~CCommunicationControl() override; // Interface map BEGIN_SDV_INTERFACE_MAP() SDV_INTERFACE_ENTRY(sdv::ps::IMarshallAccess) SDV_INTERFACE_ENTRY(sdv::com::IConnectionControl) END_SDV_INTERFACE_MAP() // Component declarations DECLARE_OBJECT_CLASS_TYPE(sdv::EObjectType::system_object) DECLARE_OBJECT_SINGLETON() DECLARE_OBJECT_CLASS_NAME("CommunicationControl") /** * @brief Initialization event, called after object configuration was loaded. Overload of sdv::CSdvObject::OnInitialize. * @return Returns 'true' when the initialization was successful, 'false' when not. */ virtual bool OnInitialize() override; /** * @brief Shutdown the object. Overload of sdv::CSdvObject::OnShutdown. */ virtual void OnShutdown() override; /** * @brief Create an IPC channel endpoint and use it for SDV communication. Overload of * sdv::com::IConnectionControl::CreateServerConnection. * @remarks The channel will be destroyed automatically when a timeout occurs (no initial connection took place within the * specified time). * @remarks The function doesn't wait until a connection has been made, but returns straight after the channel creation. * @param[in] eChannelType Type of channel to create. Must be local or remote. * @param[in] pObject Initial object to start the communication with. * @param[in] uiTimeoutMs Timeout for waiting for a connection. * @param[out] ssConnectionString String describing the connection details to connect to this channel. * @return Channel connection ID if successful or 0 if not. */ virtual sdv::com::TConnectionID CreateServerConnection(/*in*/ sdv::com::EChannelType eChannelType, /*in*/ sdv::IInterfaceAccess* pObject, /*in*/ uint32_t uiTimeoutMs, /*out*/ sdv::u8string& ssConnectionString) override; /** * @brief Connect to an SDV channel (an IPC channel managed by the channel control and waiting for an initial connection. * Overload of sdv::com::IConnectionControl::CreateClientConnection. * @remarks The connection will be destroyed automatically when a timeout occurs (no initial connection took place within * the specified time). * @param[in] ssConnectionString The string describing the connection details. * @param[in] uiTimeoutMs Timeout for waiting for a connection. * @param[out] pProxy Pointer to the object representing the remote object (a proxy to the remote object). Or nullptr * when a timeout occurred. * @return Channel connection ID if successful or 0 if not. */ virtual sdv::com::TConnectionID CreateClientConnection(/*in*/ const sdv::u8string& ssConnectionString, /*in*/ uint32_t uiTimeoutMs, /*out*/ sdv::IInterfaceAccess*& pProxy) override; /** * @brief Assign and take over an already initialized IPC channel server endpoint for use with SDV communication. Overload of * sdv::com::IConnectionControl::AssignServerEndpoint. * @remarks The channel will be destroyed automatically when a timeout occurs (no initial connection took place within the * specified time) unless the flag bAllowReconnect has been set. * @remarks The channel uses the interface sdv::IObjectLifetime to control the lifetime of the channel. If IObjectLifetime is * not available, IObjectDestroy will be used. * @remarks The function doesn't wait until a connection has been made, but returns straight after the assignment. * @param[in] pChannelEndpoint Pointer to the channel endpoint to be assigned. * @param[in] pObject Initial object to start the communication with. * @param[in] uiTimeoutMs Timeout for waiting for an initial connection. Not used when the bAllowReconnect flag has been set. * @param[in] bAllowReconnect When set, the channel is allowed to be disconnected and reconnected again. * @return Channel connection ID if successful or 0 if not. */ virtual sdv::com::TConnectionID AssignServerEndpoint(/*in*/ sdv::IInterfaceAccess* pChannelEndpoint, /*in*/ sdv::IInterfaceAccess* pObject, /*in*/ uint32_t uiTimeoutMs, /*in*/ bool bAllowReconnect) override; /** * @brief Assign and take over an already initialized IPC channel client endpoint for use with SDV communication. Overload of * sdv::com::IConnectionControl::AssignClientEndpoint. * @remarks The connection will be destroyed automatically when a timeout occurs (no initial connection took place * within the specified time). * @remarks The channel uses the interface sdv::IObjectLifetime to control the lifetime of the channel. If * IObjectLifetime is not available, IObjectDestroy will be used. * @param[in] pChannelEndpoint Pointer to the channel endpoint to be assigned. * @param[in] uiTimeoutMs Timeout for waiting for an initial connection. Not used when the bAllowReconnect flag has * been set. * @param[out] pProxy Pointer to the object representing the remote object (a proxy to the remote object). Or nullptr * when a timeout occurred. * @return Channel connection ID if successful or 0 if not. */ virtual sdv::com::TConnectionID AssignClientEndpoint(/*in*/ sdv::IInterfaceAccess* pChannelEndpoint, /*in*/ uint32_t uiTimeoutMs, /*out*/ sdv::IInterfaceAccess*& pProxy) override; /** * @brief Remove a connection with the provided connection ID. Overload of sdv::com::IConnectionControl::RemoveConnection. * @param[in] tConnectionID The connection ID of the connection to remove. */ virtual void RemoveConnection(/*in*/ const sdv::com::TConnectionID& tConnectionID) override; /** * @brief Get a proxy for the interface connection to the stub. Overload of sdv::ps::IMarshallAcess::GetProxy. * @param[in] tStubID Reference to the ID of the stub to connect to. * @param[in] id The interface ID to get the proxy for. * @return Returns the interface to the proxy object. */ virtual sdv::interface_t GetProxy(/*in*/ const sdv::ps::TMarshallID& tStubID, /*in*/ sdv::interface_id id) override; /** * @brief Get a stub for the interface with the supplied ID. Overload of sdv::ps::IMarshallAcess::GetStub. * @param[in] ifc The interface to get the stub for.. * @return Returns the Stub ID that is assigned to the interface. Or an empty ID when no stub could be found. */ virtual sdv::ps::TMarshallID GetStub(/*in*/ sdv::interface_t ifc) override; /** * @brief Create a proxy for the interface connection to the stub. * @remarks Unlike stubs, which are unique for the process they run in, proxy objects are unique within the channel they are * used - using the identification of the stub ID of the process the call. The proxy object is not stored here; just created. * @param[in] id The ID of the interface this object marshalls the calls for. * @param[in] tStubID The stub ID this proxy is communicating to. * @param[in] rConnector Reference to channel connector. * @return Returns a shared pointer to the proxy object. */ std::shared_ptr CreateProxy(sdv::interface_id id, sdv::ps::TMarshallID tStubID, CChannelConnector& rConnector); /** * @brief Get a stub for the interface with the supplied ID. Overload of sdv::ps::IMarshallAcess::GetStub. * @param[in] ifc The interface to get the stub for.. * @return Returns the Stub ID that is assigned to the interface. Or an empty ID when no stub could be found. */ std::shared_ptr GetOrCreateStub(sdv::interface_t ifc); /** * @brief To identify the send and receive packets belonging to one call, the call is identified with a unique index, which * is created here. * @return The unique call index. */ uint64_t CreateUniqueCallIndex(); /** * @brief Set the channel connector context for the current thread. This is used to marshall interfaces over the same connector. * @param[in] pConnectorContext Pointer to the connector currently being used. */ void SetConnectorContext(CChannelConnector* pConnectorContext); /** * @brief Call the stub function. * @remarks This function call is synchronous and does not return until the call has been finalized or a timeout * exception has occurred. * @remarks The sequence contains all data to make the call. It is important that the data in the sequence is * complete and in the correct order. * @param[in] tStubID ID of the stub to call. * @param[inout] seqInputData Reference to sequence of input data pointers. The first data pointer contains the * marshalling header. The second contains the parameters (if available) and the others contain raw data pointers * (if available). The call is allowed to change the sequence to be able to add additional information during the * communication without having to copy the existing data. * @return Sequence of output data pointers. The first data pointer contains the marshalling header. The second * contains the return value and parameters (if available) and the others contain raw data pointers (if available). */ sdv::sequence> CallStub(sdv::ps::TMarshallID tStubID, sdv::sequence>& seqInputData); private: std::mutex m_mtxChannels; ///< Protect the channel map. std::vector> m_vecChannels; ///< Channel vector. std::vector m_vecInitialConnectMon; ///< Initial connection monitor. std::recursive_mutex m_mtxObjects; ///< Protect object vectors. std::vector> m_vecMarshallObjects; ///< Vector with marshall objects; lifetime is handled by channel. std::map> m_mapStubObjects; ///< Map of interfaces to stub objects std::atomic_uint64_t m_uiCurrentCallCnt = 0; ///< The current call count. thread_local static CChannelConnector* m_pConnectorContext; ///< The current connector; variable local to each thread. }; DEFINE_SDV_OBJECT(CCommunicationControl) #endif // !defined COM_CTRL_H