VLink 2.0.0
A high-performance communication middleware
载入中...
搜索中...
未找到
dds_conf.h
浏览该文件的文档.
1/*
2 * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 * Author: Thun Lu <thun.lu@zohomail.cn>
4 * Repo: https://github.com/thun-res/vlink
5 * _ __ __ _ __
6 * | | / / / / (_) ____ / /__
7 * | | / / / / / / / __ \ / //_/
8 * | |/ / / /___ / / / / / / / ,<
9 * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/**
25 * @file dds_conf.h
26 * @brief Transport configuration for the @c dds:// Fast-DDS RTPS backend.
27 *
28 * @details
29 * @c DdsConf configures the eProsima Fast-DDS (Fast-RTPS) transport, which provides
30 * standards-compliant DDS pub/sub and RPC over Ethernet. It is the primary
31 * cross-machine transport in VLink and is suitable for both LAN and WAN deployments.
32 *
33 * @par Supported Node Types
34 * @c dds:// supports all six node types: @c kPublisher, @c kSubscriber, @c kServer,
35 * @c kClient, @c kSetter, and @c kGetter.
36 *
37 * @par URL Format
38 * @code
39 * dds://<topic>[?domain=<N>&depth=<N>&qos=<name>]
40 * dds://<topic>[?domain=<N>&part=<v>&topic=<v>&pub=<v>&sub=<v>&writer=<v>&reader=<v>]
41 * @endcode
42 *
43 * | Component | Description |
44 * | ---------- | ------------------------------------------------------------------------- |
45 * | @c topic | DDS topic name; formed from @c host + @c "/" + @c path |
46 * | @c domain | DDS Domain ID (@c ?domain=, default from @c VLINK_DDS_DOMAIN env var) |
47 * | @c depth | History depth for the DDS endpoint (@c ?depth=, default 0) |
48 * | @c qos | Named QoS profile registered via @c register_qos() (@c ?qos=) |
49 * | @c qos_ext | Extended QoS map: @c part, @c topic, @c pub, @c sub, @c writer, @c reader |
50 *
51 * @par QoS Registration
52 * Named QoS profiles must be registered before creating any @c dds:// nodes:
53 * @code
54 * vlink::Qos my_qos;
55 * my_qos.reliability = vlink::Reliability::kReliable;
56 * my_qos.durability = vlink::Durability::kTransientLocal;
57 * vlink::DdsConf::register_qos("my_profile", my_qos);
58 *
59 * vlink::Subscriber<MyMsg> sub("dds://my_topic?qos=my_profile");
60 * @endcode
61 *
62 * @par Type Support Registration
63 * For CDR-serialised types the DDS type support factory must be registered
64 * before any publisher or subscriber is created on that topic:
65 * @code
66 * // Register request type only (for pub/sub):
67 * vlink::DdsConf::register_topic<MyMsgPubSubType>("my_topic");
68 *
69 * // Register request + response types (for RPC):
70 * vlink::DdsConf::register_topic<MyReqPubSubType, MyRespPubSubType>("my_rpc_topic");
71 *
72 * // Register from a full URL:
73 * vlink::DdsConf::register_url<MyMsgPubSubType>("dds://my_topic?domain=1");
74 * @endcode
75 *
76 * @par Global QoS File
77 * An XML QoS profile file can be loaded at startup so that DDS participants and
78 * endpoints inherit profiles by name:
79 * @code
80 * vlink::DdsConf::load_global_qos_file("/etc/vlink/dds_profile.xml");
81 * @endcode
82 *
83 * @note This header is compiled only when @c VLINK_SUPPORT_DDS is defined.
84 * @note @c qos and @c qos_ext are mutually exclusive; setting both causes
85 * @c is_valid() to return @c false.
86 * @note Response topics are automatically registered with a @c "___resp" suffix.
87 */
88
89#pragma once
90
91#ifdef VLINK_SUPPORT_DDS
92
93#include <cstdint>
94#include <functional>
95#include <map>
96#include <shared_mutex>
97#include <string>
98#include <tuple>
99#include <vector>
100
101#include "../extension/qos.h"
102#include "../impl/conf.h"
103
104namespace eprosima::fastdds::dds {
105class TopicDataType;
106}
107
108namespace vlink {
109
110/**
111 * @struct DdsConf
112 * @brief Configuration for the @c dds:// Fast-DDS RTPS transport.
113 *
114 * @details
115 * Holds the DDS topic name, domain ID, history depth, and QoS settings.
116 * Can be constructed directly or parsed from a URL string via @c Url.
117 */
118struct VLINK_EXPORT DdsConf final : public Conf {
119 std::string topic; ///< DDS topic name (host + "/" + path from URL).
120 int32_t domain{0}; ///< DDS Domain Participant ID (non-negative).
121 int32_t depth{0}; ///< DDS history depth for the endpoint; 0 means transport default.
122 std::string qos; ///< Named QoS profile key registered via @c register_qos().
123 PropertiesMap
124 qos_ext; ///< Extended per-entity QoS map (keys: @c part, @c topic, @c pub, @c sub, @c writer, @c reader).
125
126 /**
127 * @brief Constructs a @c DdsConf with topic, domain, depth, and named QoS.
128 *
129 * @param _topic DDS topic name.
130 * @param _domain DDS domain ID; default 0.
131 * @param _depth History depth; default 0.
132 * @param _qos Named QoS profile key; empty by default.
133 */
134 explicit DdsConf(const std::string& _topic, int32_t _domain = 0, int32_t _depth = 0, const std::string& _qos = "");
135
136 /**
137 * @brief Constructs a @c DdsConf with topic, domain, and extended QoS map.
138 *
139 * @details
140 * Use this constructor when fine-grained per-entity QoS is required.
141 * @c qos and @c qos_ext are mutually exclusive; @c is_valid() returns @c false
142 * if both are non-empty.
143 *
144 * @param _topic DDS topic name.
145 * @param _domain DDS domain ID.
146 * @param _qos_ext Per-entity QoS properties map.
147 */
148 explicit DdsConf(const std::string& _topic, int32_t _domain, const PropertiesMap& _qos_ext);
149
150 /**
151 * @brief Returns @c true if all fields equal those of @p conf.
152 *
153 * @param conf Configuration to compare.
154 * @return @c true if @c topic, @c domain, @c depth, @c qos, and @c qos_ext all match.
155 */
156 [[nodiscard]] bool operator==(const DdsConf& conf) const noexcept;
157
158 /**
159 * @brief Returns @c true if any field differs from @p conf.
160 *
161 * @param conf Configuration to compare.
162 * @return Logical negation of @c operator==.
163 */
164 [[nodiscard]] bool operator!=(const DdsConf& conf) const noexcept;
165
166 /**
167 * @brief Returns @c TransportType::kDds identifying this transport.
168 *
169 * @return @c TransportType::kDds.
170 */
171 [[nodiscard]] TransportType get_transport_type() const override;
172
173 /**
174 * @brief Returns the list of currently discovered DDS topics on the given domain.
175 *
176 * @details
177 * Queries the @c DdsFactory for live topic discovery information. Each entry
178 * in the returned vector is a @c (topic_name, type_name) pair.
179 *
180 * @param _domain DDS domain ID to query.
181 * @return Vector of @c (topic_name, type_name) tuples; may be empty.
182 */
183 [[nodiscard]] static std::vector<std::tuple<std::string, std::string>> get_discovered_topics(int32_t _domain);
184
185 /**
186 * @brief Loads a Fast-DDS XML QoS profile file as the global default.
187 *
188 * @details
189 * Must be called before any @c dds:// participants are created. The profiles
190 * defined in the file are available to all Fast-DDS endpoints in the process.
191 *
192 * @param filepath Absolute or relative path to the XML QoS profile file.
193 * @return @c true if the file was loaded successfully; @c false otherwise.
194 */
195 static bool load_global_qos_file(const std::string& filepath);
196
197 /**
198 * @brief Registers a Fast-DDS type support factory for a topic by name.
199 *
200 * @details
201 * Required for CDR-serialised (non-Protobuf) message types. Must be called
202 * once per topic before any publisher or subscriber is created on that topic.
203 * An optional response type (@c TypeSupportRespT) can be registered simultaneously
204 * for RPC topics; it is stored under @c name + @c "___resp".
205 *
206 * @tparam TypeSupportT Fast-DDS @c TopicDataType subclass for the request/message type.
207 * @tparam TypeSupportRespT Fast-DDS @c TopicDataType subclass for the response type;
208 * defaults to @c void (no response type registered).
209 * @param name DDS topic name to associate the type support with.
210 */
211 template <typename TypeSupportT, typename TypeSupportRespT = void>
212 static void register_topic(const std::string& name);
213
214 /**
215 * @brief Registers a Fast-DDS type support factory for a topic derived from a URL.
216 *
217 * @details
218 * Convenience wrapper that extracts the topic name from @p name using
219 * @c UrlParser and then calls @c register_topic<TypeSupportT, TypeSupportRespT>().
220 *
221 * @tparam TypeSupportT Type support for the request/message type.
222 * @tparam TypeSupportRespT Type support for the response type; @c void if not needed.
223 * @param name Full URL string (e.g. @c "dds://my_topic?domain=1").
224 */
225 template <typename TypeSupportT, typename TypeSupportRespT = void>
226 static void register_url(const std::string& name);
227
228 /**
229 * @brief Registers a named QoS profile for use by @c dds:// nodes.
230 *
231 * @details
232 * The @p name is associated with the @p qos object and can then be referenced
233 * in URL query strings as @c ?qos=name. Names that conflict with reserved
234 * DDS entity keys (@c part, @c topic, @c pub, @c sub, @c writer, @c reader, @c depth)
235 * or that are already registered cause a fatal log and are rejected.
236 *
237 * @param name Unique profile name; must not be one of the reserved keys.
238 * @param qos @c Qos object describing the quality-of-service settings.
239 */
240 static void register_qos(const std::string& name, const Qos& qos);
241
242 private:
243 template <typename TypeSupportT>
244 static void register_topic_internal(const std::string& name);
245
246 static void register_qos_internal(const std::string& name, const Qos& qos);
247
248 static std::function<void*()> find_type_support(const std::string& name);
249
250 static const Qos& find_qos(const std::string& name);
251
252 static std::string get_topic_for_url(const std::string& url);
253
254 friend class DdsFactory;
255 static std::map<std::string, std::function<void*()>> type_support_map_;
256 static std::map<std::string, Qos> qos_map_;
257 static std::shared_mutex mtx_;
258 static constexpr const char* kRespSuffix{"___resp"};
259#ifndef VLINK_ENABLE_C_INTERFACE
261#endif
262 VLINK_ALLOW_IMPL_TYPE(kServer | kClient | kPublisher | kSubscriber | kSetter | kGetter)
263 VLINK_CONF_IMPL(DdsConf)
264};
265
266////////////////////////////////////////////////////////////////
267/// Details
268////////////////////////////////////////////////////////////////
269
270inline DdsConf::DdsConf(const std::string& _topic, int32_t _domain, int32_t _depth, const std::string& _qos)
271 : topic(_topic), domain(_domain), depth(_depth), qos(_qos) {}
272
273inline DdsConf::DdsConf(const std::string& _topic, int32_t _domain, const PropertiesMap& _qos_ext)
274 : topic(_topic), domain(_domain), qos_ext(_qos_ext) {}
275
276inline bool DdsConf::operator==(const DdsConf& conf) const noexcept {
277 return topic == conf.topic && domain == conf.domain && depth == conf.depth && qos == conf.qos &&
278 qos_ext == conf.qos_ext;
279}
280
281inline bool DdsConf::operator!=(const DdsConf& conf) const noexcept { return !(*this == conf); }
282
283inline TransportType DdsConf::get_transport_type() const { return TransportType::kDds; }
284
285template <typename TypeSupportT, typename TypeSupportRespT>
286inline void DdsConf::register_topic(const std::string& name) {
287 std::lock_guard lock(mtx_);
288 register_topic_internal<TypeSupportT>(name);
289 if constexpr (!std::is_same_v<TypeSupportRespT, void>) {
290 register_topic_internal<TypeSupportRespT>(name + kRespSuffix);
291 }
292}
293
294template <typename TypeSupportT, typename TypeSupportRespT>
295inline void DdsConf::register_url(const std::string& name) {
296 register_topic<TypeSupportT, TypeSupportRespT>(get_topic_for_url(name));
297}
298
299template <typename TypeSupportT>
300inline void DdsConf::register_topic_internal(const std::string& name) {
301 static_assert(std::is_base_of_v<eprosima::fastdds::dds::TopicDataType, TypeSupportT>, "Must be dds type.");
302
303 type_support_map_[name] = [] { return new TypeSupportT(); };
304}
305
306} // namespace vlink
307
308#endif
Abstract transport configuration base class and associated helper macros.
#define VLINK_CONF_IMPL(classname)
Standard boilerplate for concrete Conf subclass declarations.
定义 conf.h:227
#define VLINK_DECLARE_GLOBAL_PROPERTY()
Declares per-transport global state: thread count and property storage.
定义 conf.h:292
#define VLINK_ALLOW_IMPL_TYPE(type)
Declares a static constexpr bitmask of supported ImplType values.
定义 conf.h:268
#define VLINK_EXPORT
定义 macros.h:85
Quality of Service (QoS) policy aggregate for VLink publishers and subscribers.