17.1. RPC over DDS Request-Reply API overview

Fast DDS DomainParticipant provides a high-level Request-Reply API to create all the DDS entities required for RPC over DDS communication. The API provides methods for creating and deleting three types of entities:

  • Service: Represents the subset of DDS entities associated with a DomainParticipant that participate in the same RPC Request/Reply communication. This includes the topics where Requests and Replies are published and the endpoints responsible for publishing and receiving Requests and Replies, which are grouped in Requesters and Repliers.

  • Requester: Represents the subset of DDS entities, associated with a Service instance, responsible for processing samples on the client side. This includes a DataWriter for publishing Request samples and a DataReader for receiving Reply samples.

  • Replier: Represents the subset of DDS entities, associated with a Service instance, responsible for processing samples on the server side. This includes a DataWriter for publishing Reply samples and a DataReader for receiving Request samples.

All these entities inherit from the abstract base class RPCEntity, which represents a generic entity in the context of RPC over DDS communication. According to RPC over DDS Standard, each entity has two different states: enabled and disabled. A disabled entity is an entity that has been created but is ignored by the middleware, so it does not participate in the communication.

User can enable and disable an entity using enable() and close() methods, respectively. Internally, when an entity is enabled, the middleware creates the DDS entities associated with it. Similarly, when an entity is disabled, the middleware deletes their DDS entities.

Note

Trying to use an RPC entity (Requester or Replier) for RPC communication when it is disabled will return an error. The user can check if an entity is enabled using is_enabled() method.

To match a request with a reply, Requesters and Repliers use a correlation mechanism. When a Request sample is sent, Requester associates a unique identifier to it represented by RequestInfo struct.

This identifier contains a SampleIdentity instance, which is formed by the Requester’s DataWriter Guid_t and a sequence number, and can be accessed through related_sample_identity member. When a Replier takes a new received Request sample, it extracts the related_sample_identity information and uses it to create a new RequestInfo which is then associated to the Reply sample.

RequestInfo works like a way to match a Reply with a previously sent Request: when a Requester receives a Reply sample, correlation of Requests and Replies is done by comparing both RequestInfo instances. If they are the same, the Reply sample is associated with the Request sample.

A request/reply communication can be established between different DomainParticipants on the same domain if they have Requesters and Repliers in the same Service. In a multiple Requester scenario (for example, one Requester per DomainParticipant), reply samples sent by each Replier will be received by all Requester’s DataReaders, whether it corresponds to a request sample sent by its associated Requester or not. Replier adds to each reply sample the Guid_t of the DataWriter which sent its associated request sample, so reply samples are filtered on Requester side creating a ContentFilteredTopic from the Reply Topic. The content filtered topic filters reply samples comparing the DataReader’s GuidPrefix_t with the GuidPrefix_t of the received related_sample_identity, so only replier samples associated to request samples sent by the same DomainParticipant are received. When a Requester is created, its DataReader is created from this ContentFilteredTopic instance.