.. _architecture_transport: Transport module ================ .. raw:: html .. raw:: html :file: ../figures/svg_href_loader.html .. raw:: html :file: ../figures/stack_diagram.svg .. include:: ../safety_manual/rules/RULE_TRANSPORT_MODULE_NOT_ALLOW.inc The Transport module is responsible for interfacing with the underlying transport system. This module provides the following interfaces: * `transport::ITransport <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_i_transport.html>`__ * `transport::IGUIDLocatorDatabase <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_i_g_u_i_d_locator_database.html>`__ The transport module is related to the following layers: .. * :ref:`architecture_discovery` by the :ref:`architecture_discovery_ilocatorobserver`. .. * :ref:`architecture_protocol` by the :ref:`architecture_protocol_imessagesink`. * :ref:`architecture_discovery` by the ``discovery::ILocatorObserver`` interface. * :ref:`architecture_protocol` by the ``protocol::IMessageSink`` interface. * :ref:`architecture_execution` by the :ref:`architecture_execution_ispinnable`. .. _architecture_transport_default_transport: Default transport ----------------- If Safe DDS has been built with any built-in transport support using the ``SAFEDDS_TRANSPORT`` (see :ref:`installation_cmake_options`), the default transport can be created using the system-wide ``create_transport`` method. This API will be used internally by the :ref:`dds_layers_domain_participant_factory` to instantiate :ref:`dds_layers_domain_participant` entities. .. literalinclude:: ../code/architecture_reference/main.cpp :language: c++ :start-after: // HANDLING_DEFAULT_SYSTEM_TRANSPORT_CREATION :end-before: //! HANDLING_DEFAULT_SYSTEM_TRANSPORT_CREATION :dedent: 8 .. note:: Provided transport implementations use the `transport::PreallocGUIDLocatorDatabse <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_prealloc_g_u_i_d_locator_database.html>`__ class to store and handle discovered locators. .. _architecture_transport_itransportinterface: ITransport interface -------------------- .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport`` interface, check API Reference: - `transport::ITransport <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_i_transport.html>`__ In general, ``transport::ITransport`` allows for sending messages to a certain destination and for listening to incoming messages: #. In order to send a message the :ref:`architecture_transport_commit_message` and :ref:`architecture_transport_commit_message_to_group` methods will be used. #. In order to listen to messages, the Safe DDS transport interface provides two different approaches: * :ref:`architecture_transport_listen_message` method allows the transport to listen to incoming messages for a given period of time. * The ``transport::ITransport`` implements :ref:`architecture_execution_ispinnable`, allowing the incoming messages reception to be performed in a non-blocking way using the Safe DDS :ref:`architecture_execution`. #. Additionally, ``transport::ITransport`` provides methods for: * Notifying newly discovered locators in order to store the relationship between entity identifiers and transport locators via :ref:`architecture_transport_on_locator_discovered` and :ref:`architecture_transport_on_group_discovered` methods. * Notifying when a locator or an endpoint group is not required anymore via :ref:`architecture_transport_on_locator_unregistered` and :ref:`architecture_transport_on_group_unregistered` methods respectively. * Retrieving the maximum size of a message that can be sent by the transport via the :ref:`architecture_transport_get_message_max_size` method. * Listening on a certain locator via the :ref:`architecture_transport_listen_on_locator` method. * Given a hint, listen on the first available locator found via the :ref:`architecture_transport_listen_on_first_available_locator` method. * Waiting for a message to be available for processing via the :ref:`architecture_transport_wait_until_message_available` method. * Setting message observers for incoming messages to be called when a new message is received (and the transport implements :ref:`architecture_execution_ispinnable`) via the :ref:`architecture_transport_set_message_observer` method. .. _architecture_transport_get_message_max_size: get_message_max_size ^^^^^^^^^^^^^^^^^^^^ This method is invoked by Safe DDS layers to retrieve the maximum size of a message that the transport can send. It has no parameters and returns the maximum size of a message as ``uint32_t``. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::get_message_max_size`` method, check API Reference: - `protocol::IMessageSink::get_message_max_size <../doxygen/classeprosima_1_1safedds_1_1protocol_1_1_i_message_sink.html>`__ .. _architecture_transport_commit_message: commit_message ^^^^^^^^^^^^^^ This method is invoked when an entity has a new message ready to be sent. The transport implementation must send the message (provided as ``memory::IList``) to the destination ``protocol::GUID``. This callback receives the following parameters: * Message buffer as ``memory::IList`` This object contains one or more memory segments that should be sent to the destination as a single message. * Origin as ``protocol::GUID`` GUID of the entity that is sending the message. * Destination as ``protocol::GUID`` GUID of the entity that shall receive the message. * Timepoint as ``execution::Timepoint`` Timeout for the message to be sent. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::commit_message`` method, check API Reference: - `protocol::IMessageSink::commit_message <../doxygen/classeprosima_1_1safedds_1_1protocol_1_1_i_message_sink.html>`__ .. _architecture_transport_commit_message_to_group: commit_message_to_group ^^^^^^^^^^^^^^^^^^^^^^^ This method is invoked when an entity has a new message ready to be sent to a group of wire protocol message sinks. The transport implementation must send the message (provided as ``memory::IList``) to the destination ``protocol::EndpointGroup``. This callback receives the following parameters: * Message buffer as ``memory::IList`` This object contains one or more memory segments that should be sent to the destination as a single message. * Origin as ``protocol::GUID`` GUID of the entity that is sending the message. * Destination as ``protocol::EndpointGroup`` Group of entities locators that shall receive the message. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::commit_message_to_group`` method, check API Reference: - `protocol::IMessageSink::commit_message_to_group <../doxygen/classeprosima_1_1safedds_1_1protocol_1_1_i_message_sink.html>`__ .. _architecture_transport_set_message_observer: set_message_observer ^^^^^^^^^^^^^^^^^^^^ This method allows the transport to receive a ``transport::IMessageObserver`` that will be notified when a new message is received in the spin operation of the transport. These message observers are intended to be notified about the reception of a message using the :ref:`architecture_execution_ispinnable`. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::set_message_observer`` method, check API Reference: - `transport::ITransport::set_message_observer <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_i_transport.html#a05aab5f72ef1a59bfad7c0fb6448c2ce>`__ .. _architecture_transport_listen_on_locator: listen_on_locator ^^^^^^^^^^^^^^^^^ This method is invoked by Safe DDS layers for the transport to start listening on a specific locator. This callback returns a ``safedds::ReturnCode`` and receives the following parameters: * Locator as ``transport::Locator`` Locator to listen on. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::listen_on_locator`` method, check API Reference: - `transport::IMessageListener::listen_on_locator <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_i_message_listener.html#a98c7e828710aaa3236bd08daf1bc33ea>`__ .. _architecture_transport_listen_on_first_available_locator: listen_on_first_available_locator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This method is invoked by Safe DDS layers to get a listen locator when the ``DomainParticipantWireProtocolQosPolicy::announced_locator`` is not configured. This method shall return a valid ``transport::Locator`` which is already configured to listen to messages. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::listen_on_first_available_locator`` method, check API Reference: - `transport::IMessageListener::listen_on_first_available_locator <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_i_message_listener.html#acfeb68d2b3651f86e3707cf9c1164ef2>`__ .. _architecture_transport_listen_message: listen_message ^^^^^^^^^^^^^^ This method enables the transport to listen for incoming messages in any of the locators that have been previously registered with the :ref:`architecture_transport_listen_on_locator` method during a give period of time. This callback returns a ``transport::Locator`` and receives the following parameters: * Incoming message buffer as ``memory::IMutableByteArrayView`` This object contains one memory segment that shall be filled with the received message. * Reception locator as ``transport::Locator`` Output parameter with the Locator where the message has been received. * Timepoint as ``execution::Timepoint`` Timeout for the message to be received. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::listen_on_locator`` method, check API Reference: - `transport::IMessageListener::listen_message <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_i_message_listener.html#acfeb68d2b3651f86e3707cf9c1164ef2>`__ .. _architecture_transport_wait_until_message_available: wait_until_message_available ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This method waits up to a given timeout until the transport has a message available for processing. This callback returns a boolean indicating whether a message is available and receives the following parameters: * Timepoint as ``execution::Timepoint`` Timeout for the message to be received. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::wait_until_message_available`` method, check API Reference: - `transport::IMessageListener::wait_until_message_available <../doxygen/classeprosima_1_1safedds_1_1transport_1_1_i_message_listener.html#a23cf35720b01cc3236b43886cb5b5bad>`__ .. _architecture_transport_on_locator_discovered: on_locator_discovered ^^^^^^^^^^^^^^^^^^^^^ This method is invoked when a new locator is identified, possibly by the :ref:`architecture_discovery`. The transport implementation may require to store the provided ``protocol::GUID`` and ``transport::Locator`` for future use. The stored information can be useful when implementing the :ref:`architecture_transport_commit_message` method, as this method will provide origin and destination locators of a certain message. This callback receives the following parameters: * Discovered entity GUID as ``protocol::GUID`` GUID of the entity that has been discovered. * Metatraffic flag as ``bool`` Indicates whether the locator belongs to metatraffic. * Discovered entity locator as ``transport::Locator`` Locator of the entity that has been discovered. * Discoverer entity GUIDPrefix as ``protocol::GUIDPrefix`` GUIDPrefix of the entity that discovered the locator. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::on_locator_discovered`` method, check API Reference: - `discovery::ILocatorObserver::on_locator_discovered <../doxygen/classeprosima_1_1safedds_1_1discovery_1_1_i_locator_observer.html#af41f42864bfb9ce57fc4a3eea2102c6a>`__ .. _architecture_transport_on_group_discovered: on_group_discovered ^^^^^^^^^^^^^^^^^^^ This method is invoked when a new endpoint group is identified, possibly by the :ref:`architecture_discovery`. The transport implementation may require to store the provided ``protocol::EndpointGroup`` and ``protocol::EndpointGroup`` for future use. The stored information can be useful when implementing the :ref:`architecture_transport_commit_message_to_group` method, as this method will provide origin and destination locators of a certain message. This callback receives the following parameters: * Discovered endpoint group as ``protocol::EndpointGroup`` Group that has been discovered. * Metatraffic flag as ``bool`` Indicates whether the locator belongs to metatraffic. * Discovered entity locator as ``transport::Locator`` Locator of the entity that has been discovered. * Discoverer entity GUIDPrefix as ``protocol::GUIDPrefix`` GUIDPrefix of the entity that discovered the locator. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::on_group_discovered`` method, check API Reference: - `discovery::ILocatorObserver::on_group_discovered <../doxygen/classeprosima_1_1safedds_1_1discovery_1_1_i_locator_observer.html#af897e757358f82793763330264d77d2d>`__ .. _architecture_transport_on_locator_unregistered: on_locators_unregistered ^^^^^^^^^^^^^^^^^^^^^^^^ This method is invoked when a previously discovered locator is removed, possibly by the :ref:`architecture_discovery`. The transport implementation may require to remove the stored ``protocol::GUID``. This callback receives the following parameters: * Unregistered entity GUID as ``protocol::GUID`` GUID of the entity that has been unregistered. * Discoverer entity GUIDPrefix as ``protocol::GUIDPrefix`` GUIDPrefix of the entity that received the unregister event. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::on_locators_unregistered`` method, check API Reference: - `discovery::ILocatorObserver::on_locators_unregistered <../doxygen/classeprosima_1_1safedds_1_1discovery_1_1_i_locator_observer.html#ab68338a7fb452199b54887dfd656395f>`__ .. _architecture_transport_on_group_unregistered: on_group_unregistered ^^^^^^^^^^^^^^^^^^^^^ This method is invoked when a previously discovered endpoint group is removed, possibly by the :ref:`architecture_discovery`. The transport implementation may require to remove the stored ``protocol::EndpointGroup``. This callback receives the following parameters: * Unregistered endpoint group as ``protocol::EndpointGroup`` Group that has been unregistered. * Discoverer entity GUIDPrefix as ``protocol::GUIDPrefix`` GUIDPrefix of the entity that received the unregister event. .. admonition:: API Reference :class: seealso For more information about ``transport::ITransport::on_group_unregistered`` method, check API Reference: - `discovery::ILocatorObserver::on_group_unregistered <../doxygen/classeprosima_1_1safedds_1_1discovery_1_1_i_locator_observer.html#a1634d83f72dae2f2ef3caddb59d27c3f>`__ Example implementation ---------------------- .. note:: For complete transport implementation, please refer to the `POSIX UDPv4 transport <../doxygen/classeprosima_1_1safedds_1_1transport_1_1posix_1_1_u_d_pv4.html>`__ implementation in Safe DDS code base. A naive Safe DDS transport implementation that sends messages to a remote host using an abstract transport is provided in the following example: .. literalinclude:: ../code/architecture_reference/main.cpp :language: c++ :start-after: // REFERENCE_TRANSPORT_IMPLEMENTATION :end-before: //! REFERENCE_TRANSPORT_IMPLEMENTATION