.. _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