/src/Fast-DDS/src/cpp/fastdds/rpc/ServiceImpl.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima). |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef FASTDDS_RPC__SERVICEIMPL_HPP |
16 | | #define FASTDDS_RPC__SERVICEIMPL_HPP |
17 | | |
18 | | #include <mutex> |
19 | | |
20 | | #include <fastdds/dds/domain/qos/ReplierQos.hpp> |
21 | | #include <fastdds/dds/domain/qos/RequesterQos.hpp> |
22 | | #include <fastdds/dds/rpc/Service.hpp> |
23 | | #include <fastdds/dds/topic/ContentFilteredTopic.hpp> |
24 | | #include <fastdds/dds/topic/Topic.hpp> |
25 | | |
26 | | #include "../domain/DomainParticipantImpl.hpp" |
27 | | #include "../publisher/PublisherImpl.hpp" |
28 | | #include "../subscriber/SubscriberImpl.hpp" |
29 | | |
30 | | namespace eprosima { |
31 | | namespace fastdds { |
32 | | namespace dds { |
33 | | namespace rpc { |
34 | | |
35 | | class ReplierImpl; |
36 | | class RequesterImpl; |
37 | | |
38 | | /** |
39 | | * @brief Class that represents the implementation of a Service entity |
40 | | */ |
41 | | class ServiceImpl : public Service |
42 | | { |
43 | | |
44 | | public: |
45 | | |
46 | | /** |
47 | | * @brief Constructor |
48 | | * Don't use it directly, use create_service from DomainParticipant instead |
49 | | */ |
50 | | ServiceImpl( |
51 | | const std::string& service_name, |
52 | | const std::string& service_type_name, |
53 | | DomainParticipantImpl* participant, |
54 | | PublisherImpl* service_publisher, |
55 | | SubscriberImpl* service_subscriber); |
56 | | |
57 | | /** |
58 | | * @brief Destructor |
59 | | */ |
60 | | virtual ~ServiceImpl(); |
61 | | |
62 | | /** |
63 | | * @brief Get the service name |
64 | | * |
65 | | * @return Service name |
66 | | */ |
67 | | const std::string& get_service_name() const override |
68 | 0 | { |
69 | 0 | return service_name_; |
70 | 0 | } |
71 | | |
72 | | /** |
73 | | * @brief Get the service type name |
74 | | * |
75 | | * @return Service type name |
76 | | */ |
77 | | const std::string& get_service_type_name() const override |
78 | 0 | { |
79 | 0 | return service_type_name_; |
80 | 0 | } |
81 | | |
82 | | /** |
83 | | * @brief Remove a requester from the service |
84 | | * |
85 | | * @param requester Requester to remove |
86 | | * @return RETCODE_OK if the requester was removed successfully, an specific error code otherwise |
87 | | */ |
88 | | ReturnCode_t remove_requester( |
89 | | RequesterImpl* requester); |
90 | | |
91 | | /** |
92 | | * @brief Remove a replier from the service |
93 | | * |
94 | | * @param replier replier to remove |
95 | | * @return RETCODE_OK if the requester was removed successfully, an specific error code otherwise |
96 | | */ |
97 | | ReturnCode_t remove_replier( |
98 | | ReplierImpl* replier); |
99 | | |
100 | | /** |
101 | | * @brief Create a requester for the service |
102 | | * |
103 | | * @param qos Requester QoS |
104 | | * @return A pointer to the created requester or nullptr if an error occurred |
105 | | */ |
106 | | RequesterImpl* create_requester( |
107 | | const RequesterQos& qos); |
108 | | |
109 | | /** |
110 | | * @brief Create a replier for the service |
111 | | * |
112 | | * @param qos Replier QoS |
113 | | * @return A pointer to the created replier or nullptr if an error occurred |
114 | | */ |
115 | | ReplierImpl* create_replier( |
116 | | const ReplierQos& qos); |
117 | | |
118 | | /** |
119 | | * @brief Enable the service |
120 | | * |
121 | | * @return RETCODE_OK if the topics were created successfully, an specific error code otherwise |
122 | | * It will also try to enable all internal Requesters and Repliers |
123 | | */ |
124 | | ReturnCode_t enable() override; |
125 | | |
126 | | /** |
127 | | * @brief Disable the service |
128 | | * |
129 | | * @return RETCODE_OK if all topics were deleted and all internal requesters/repliers were disabled, |
130 | | * an specific error code otherwise |
131 | | */ |
132 | | ReturnCode_t close() override; |
133 | | |
134 | | /** |
135 | | * @brief Check if the service is enabled |
136 | | */ |
137 | | inline bool is_enabled() const override |
138 | 0 | { |
139 | 0 | return enabled_; |
140 | 0 | } |
141 | | |
142 | | bool service_type_in_use( |
143 | | const std::string& service_type_name) const |
144 | 0 | { |
145 | 0 | return service_type_name_ == service_type_name; |
146 | 0 | } |
147 | | |
148 | | /** |
149 | | * @brief Check if the service is empty (i.e: it has neither requesters nor repliers) |
150 | | */ |
151 | | inline bool is_empty() const |
152 | 0 | { |
153 | 0 | return repliers_.empty() && requesters_.empty(); |
154 | 0 | } |
155 | | |
156 | | /** |
157 | | * @brief Validate the requester/replier's QoS. They should be consistent with the service configuration |
158 | | * |
159 | | * @param qos QoS to validate |
160 | | * @return True if the parameters are valid, false otherwise |
161 | | */ |
162 | | template <typename T> |
163 | | bool validate_qos( |
164 | | const T& qos) |
165 | 0 | { |
166 | |
|
167 | 0 | bool valid = true; |
168 | |
|
169 | 0 | if (qos.writer_qos.reliability().kind != RELIABLE_RELIABILITY_QOS) |
170 | 0 | { |
171 | 0 | EPROSIMA_LOG_ERROR(SERVICE, "Writer QoS reliability must be RELIABLE_RELIABILITY_QOS"); |
172 | 0 | valid = false; |
173 | 0 | } |
174 | |
|
175 | 0 | if (qos.reader_qos.reliability().kind != RELIABLE_RELIABILITY_QOS) |
176 | 0 | { |
177 | 0 | EPROSIMA_LOG_ERROR(SERVICE, "Reader QoS reliability must be RELIABLE_RELIABILITY_QOS"); |
178 | 0 | valid = false; |
179 | 0 | } |
180 | |
|
181 | 0 | return valid; |
182 | 0 | } Unexecuted instantiation: bool eprosima::fastdds::dds::rpc::ServiceImpl::validate_qos<eprosima::fastdds::dds::RequesterQos>(eprosima::fastdds::dds::RequesterQos const&) Unexecuted instantiation: bool eprosima::fastdds::dds::rpc::ServiceImpl::validate_qos<eprosima::fastdds::dds::ReplierQos>(eprosima::fastdds::dds::ReplierQos const&) |
183 | | |
184 | | DomainParticipantImpl* get_participant() |
185 | 0 | { |
186 | 0 | return participant_; |
187 | 0 | } |
188 | | |
189 | | PublisherImpl* get_publisher() |
190 | 0 | { |
191 | 0 | return service_publisher_; |
192 | 0 | } |
193 | | |
194 | | SubscriberImpl* get_subscriber() |
195 | 0 | { |
196 | 0 | return service_subscriber_; |
197 | 0 | } |
198 | | |
199 | | Topic* get_request_topic() |
200 | 0 | { |
201 | 0 | return request_topic_; |
202 | 0 | } |
203 | | |
204 | | Topic* get_reply_topic() |
205 | 0 | { |
206 | 0 | return reply_topic_; |
207 | 0 | } |
208 | | |
209 | | ContentFilteredTopic* get_reply_filtered_topic() |
210 | 0 | { |
211 | 0 | return reply_filtered_topic_; |
212 | 0 | } |
213 | | |
214 | | private: |
215 | | |
216 | | /** |
217 | | * @brief Create request and reply topics for the service |
218 | | * |
219 | | * @return RETCODE_OK if request/reply topics were created successfully, an specific error code otherwise |
220 | | */ |
221 | | ReturnCode_t create_request_reply_topics(); |
222 | | |
223 | | /** |
224 | | * @brief Delete all internal Requester and Replier entities |
225 | | * |
226 | | * @return RETCODE_OK if all entities were deleted successfully, an specific error code otherwise |
227 | | */ |
228 | | ReturnCode_t delete_contained_entities(); |
229 | | |
230 | | //! Service name |
231 | | std::string service_name_; |
232 | | |
233 | | //! Service type name |
234 | | std::string service_type_name_; |
235 | | |
236 | | //! Request topic info |
237 | | std::string request_topic_name_; |
238 | | std::string request_type_name_; |
239 | | |
240 | | //! Reply topic info |
241 | | std::string reply_topic_name_; |
242 | | std::string reply_type_name_; |
243 | | std::string reply_filtered_topic_name_; |
244 | | |
245 | | //! DDS Participant associated with the service |
246 | | DomainParticipantImpl* participant_; |
247 | | |
248 | | //! DDS Publisher used to create DataWriters for Requesters and Repliers |
249 | | PublisherImpl* service_publisher_; |
250 | | |
251 | | //! DDS Subscriber used to create DataReaders for Requesters and Repliers |
252 | | SubscriberImpl* service_subscriber_; |
253 | | |
254 | | //! Vector of repliers attached to the service |
255 | | std::vector<ReplierImpl*> repliers_; |
256 | | |
257 | | //! Mutex to protect the repliers list |
258 | | std::mutex mtx_repliers_; |
259 | | |
260 | | //! Vector of requesters attached to the service |
261 | | std::vector<RequesterImpl*> requesters_; |
262 | | |
263 | | //! Mutex to protect the requesters list |
264 | | std::mutex mtx_requesters_; |
265 | | |
266 | | //! Request and Reply topics associated with the service |
267 | | // NOTE: These topics do not filter samples. They are used to create the content filtered topics |
268 | | // If we use these topics to publish/subscribe in a multiple requester - single replier service scenario, |
269 | | // The requesters will receive all the replies, not only the ones that match their requests |
270 | | Topic* request_topic_; |
271 | | Topic* reply_topic_; |
272 | | |
273 | | //! Request and Reply filtered topics associated with the service. |
274 | | // In a multiple requester - single replier service scenario, each requester will discard the received replies destinated to another requester |
275 | | ContentFilteredTopic* reply_filtered_topic_; |
276 | | |
277 | | bool enabled_; |
278 | | |
279 | | }; |
280 | | |
281 | | } // namespace rpc |
282 | | } // namespace dds |
283 | | } // namespace fastdds |
284 | | } // namespace eprosima |
285 | | |
286 | | #endif // FASTDDS_RPC__SERVICEIMPL_HPP |