17.1.1. RPC Service

A Service is the RPCEntity used to register all RPCEntities involved in an RPC communication, both on the client side (Requesters) and on the server side (Repliers). Two or more participants can communicate with each other via RPC if they register the same service and create Requesters and Repliers in it.

A service is represented by its name and a Service type, so that two Service instances represent the same RPC service if they have the same name and type. The name of the Service and the name of its type can be obtained through the methods get_service_name() and get_service_type_name() respectively.

Similarly to the rest of the RPC entities, Service instances can be enabled or disabled, according to whether they contain DDS entities or not:

  • Each active Service contains at least two DDS entities: a Request Topic, which is used to publish and receive Request samples, and a Reply Topic, which is used to publish and receive Reply samples. If it also contains enabled Requesters and Repliers, it also includes their respective internal DataWriters and DataReaders. Therefore, an enabled Service instance can also be understood as the subset of DDS entities associated with a DomainParticipant that participate in the same communication through RPC.

  • Each disabled Replier does not contain any DDS entity and is ignored by the middleware. Therefore, it cannot take requests nor send replies.

17.1.1.1. Service types

Due to the fact that a Service represents a Request/Reply communication, a Service type is represented by a pair of topic types: the Request topic type and the Reply topic type. A new Service type can be defined creating an instance of ServiceTypeSupport class, which is constructed using TypeSupport instances of both Request and Reply types.

DomainParticipant class have register_service_type() and unregister_service_type() methods to register and unregister a ServiceTypeSupport instance, respectively.

Note

Request and Reply types associated with a service type named <service_type_name> are registered in the participant with the names <service_type_name>_Request` and <service_type_name>_Reply, respectively.

A registered ServiceTypeSupport can be found by name using find_service_type() method; if a Service type with the provided name is not found, an empty ServiceTypeSupport is returned.

Note

Trying to register a different ServiceTypeSupport instance with a service_type_name already registered will return a ReturnCode_t error.

Registering and unregistering a ServiceTypeSupport instance involves registering and unregistering the Request and Reply types in the participant, respectively. If a ServiceTypeSupport contains a Request or Reply type with the same name as a previously registered type but with a different TypeSupport, the register_service_type() method will fail. Similarly, attempting to unregister a ServiceTypeSupport instance with a Request or Reply type that is used by a DDS endpoint on a topic not created by the Service will fail. To avoid these issues, it is recommended to make sure that the Request and Reply types are reserved for RPC communication though a unique service and not used by external DDS entities which are not part of the Service.

17.1.1.2. Creating and deleting a Service

A DomainParticipant can create and register a Service instance using DomainParticipant::create_service() method. Respectively, a Service can be unregistered and deleted using DomainParticipant::delete_service() method. Each registered Service can be found by name using DomainParticipant::find_service() method.

Note

Before creating a new Service, user must register the ServiceTypeSupport instance associated with the Service type. If there is no Service type registered with the service_type_name provided, Service is not created and DomainParticipant::create_service() method will return a null pointer.

When a new Service is created, it is enabled by default. It means that DomainParticipant creates the topics used for publishing and receiving Request and Reply samples.

Note

If the DomainParticipant is unable to enable the Service when it is created, it is considered an error. The instance is destroyed, and DomainParticipant::create_service() returns nullptr.

Only the DomainParticipant that created the Service instance can delete it. Attempting to delete a Service instance from a different DomainParticipant will result in a ReturnCode_t error.

17.1.1.3. Enabling and disabling a Service

Service instances can be enabled or disabled using enable() and close() methods, respectively.

When a disabled Service instance is enabled, new Request and Reply topics are created in the DomainParticipant using the registered Service type. It also creates the content filtered topic used for Reply samples. Additionally, if it contains Requesters and Repliers, an attempt will be made to enable all possible entities.

Note

Request and Reply topics are created with names <service_name>_Request and <service_name>_Reply, respectively. The ContentFilteredTopic instance is also created from the Reply topic instance with name <service_name>_ReplyFiltered.

Note

If some of the RPCEntities within the Service cannot be enabled, an error log is displayed. However, enable() ignores this failure and returns RETCODE_OK` as long as the topics have been created successfully.

Reciprocally, when an enabled Service is disabled, all the DDS entities that the Service contains are destroyed, making the Service not participate in the communication through RPC. It implies disabling all containing Requesters and Repliers and deleting the Request and Reply topics.

Note

If some of the RPCEntities within the Service cannot be disabled, close() returns an error code.

17.1.1.4. Example

The following code snippet shows how to create and delete a Service instance:

        TypeSupport request_type_support = TypeSupport(new CustomDataType());
        TypeSupport reply_type_support = TypeSupport(new CustomDataType());
        DomainParticipant* participant =
            DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);

        // Create a new ServiceTypeSupport instance
        ServiceTypeSupport service_type_support(request_type_support, reply_type_support);

        // Register the ServiceTypeSupport instance in a DomainParticipant
        ReturnCode_t ret;
        ret = participant->register_service_type(service_type_support, "ServiceType");
        if (RETCODE_OK != ret)
        {
            // Error
            return;
        }

        // Create a new Service instance
        Service* service = participant->create_service("Service", "ServiceType");
        if (!service)
        {
            // Error
            return;
        }

        // ... Create Requesters and Repliers here

        // Delete the created Service
        ret = participant->delete_service(service);
        if (RETCODE_OK != ret)
        {
            // Error
            return;
        }