OpenDDS  Snapshot(2023/04/28-20:55)
DCPS_Utils.cpp
Go to the documentation of this file.
1 /*
2  *
3  *
4  * Distributed under the OpenDDS License.
5  * See: http://www.opendds.org/license.html
6  */
7 
8 #include "DCPS/DdsDcps_pch.h"
9 #include "DCPS_Utils.h"
10 
11 #include "Qos_Helper.h"
12 #include "Definitions.h"
13 #include "SafetyProfileStreams.h"
14 
15 #include <ace/ACE.h> /* For ACE::wild_match() */
16 #include <ace/OS_NS_string.h>
17 
18 #ifdef OPENDDS_SECURITY
19 # include "dds/DdsSecurityCoreC.h"
20 #endif
21 
22 #include <cstring>
23 
25 
26 namespace OpenDDS {
27 namespace DCPS {
28 
30 {
31  switch (value) {
32  case DDS::RETCODE_OK:
33  return "OK";
34  case DDS::RETCODE_ERROR:
35  return "Error";
37  return "Unsupported";
39  return "Bad parameter";
41  return "Precondition not met";
43  return "Out of resources";
45  return "Not enabled";
47  return "Immutable policy";
49  return "Inconsistent policy";
51  return "Already deleted";
53  return "Timeout";
55  return "No data";
57  return "Illegal operation";
58 #ifdef OPENDDS_SECURITY
60  return "Not allowed by security";
61 #endif
62  default:
63  ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: retcode_to_string: ")
64  ACE_TEXT("%d is either invalid or not recognized.\n"),
65  value));
66  return "Invalid return code";
67  }
68 }
69 
71 {
72  switch (value) {
73  case CREATED:
74  return "Created";
75  case ENABLED:
76  return "Enabled";
77  case FOUND:
78  return "Found";
79  case NOT_FOUND:
80  return "Not found";
81  case REMOVED:
82  return "Removed";
84  return "Conflicting typename";
86  return "Precondition not met";
87  case INTERNAL_ERROR:
88  return "Internal error";
89  case TOPIC_DISABLED:
90  return "Topic disabled";
91  default:
92  ACE_ERROR((LM_ERROR, ACE_TEXT("(%P|%t) ERROR: topicstatus_to_string: ")
93  ACE_TEXT("%d is either invalid or not recognized.\n"),
94  value));
95  return "Invalid topic status";
96  }
97 }
98 
99 bool
100 is_wildcard(const char *str)
101 {
102  static const char wild[] = "?*[";
103 
104  while (*str) {
105  size_t i = ACE_OS::strcspn(str, wild);
106 
107  if (!str[i]) return false; // no wildcard
108 
109  if (i > 0 && str[i-1] == '\\') str += i + 1; // escaped wildcard
110 
111  else return true;
112  }
113 
114  return false;
115 }
116 
118 public:
119  PartitionName(const char* name)
120  : name_(name),
121  wildcard_(is_wildcard(name)) {}
122 
123  bool matches(const PartitionName& n) {
124  if (wildcard_ && n.wildcard_)
125  return false; // wildcards never match
126 
127  if (wildcard_)
128  return ACE::wild_match(n.name_, name_, true, true);
129 
130  else if (n.wildcard_)
131  return ACE::wild_match(name_, n.name_, true, true);
132 
133  else
134  return ACE_OS::strcmp(name_, n.name_) == 0;
135  }
136 
137 private:
138  const char* name_;
139  bool wildcard_;
140 };
141 
142 bool
144 {
145  for (CORBA::ULong i = 0; i < qos.name.length(); ++i) {
146  PartitionName qos_name(qos.name[i]);
147 
148  if (qos_name.matches(name))
149  return true;
150  }
151 
152  return false;
153 }
154 
155 bool
157 {
158  if (qos.name.length() == 0)
159  return true; // default
160 
161  for (CORBA::ULong i = 0; i < qos.name.length(); ++i) {
162  if (*qos.name[i] == 0)
163  return true; // default (empty string)
164  }
165 
166  return false;
167 }
168 
169 bool
171  const DDS::PartitionQosPolicy& sub)
172 {
173  if (matches_default(pub)) {
174  if (matches_default(sub))
175  return true;
176 
177  // Zero-length sequences should be treated the same as a
178  // sequence of length 1 that contains an empty string:
179  if (pub.name.length() == 0)
180  return matches_name(sub, "");
181  }
182 
183  for (CORBA::ULong i = 0; i < pub.name.length(); ++i) {
184  const char* name = pub.name[i];
185 
186  if (matches_name(sub, name))
187  return true;
188  }
189 
190  return false;
191 }
192 
193 void
195  DDS::QosPolicyId_t incompatible_policy)
196 {
197  if (!status) return;
198 
199  ++status->total_count;
200  ++status->count_since_last_send;
201  status->last_policy_id = incompatible_policy;
202  CORBA::ULong const size = status->policies.length();
203  CORBA::ULong count = 0;
204  bool updated = false;
205 
206  for (; !updated && count < size; ++count) {
207  if (status->policies[count].policy_id == incompatible_policy) {
208  ++status->policies[count].count;
209  updated = true;
210  }
211  }
212 
213  if (!updated) {
214  DDS::QosPolicyCount policy;
215  policy.policy_id = incompatible_policy;
216  policy.count = 1;
217  status->policies.length(count + 1);
218  status->policies[count] = policy;
219  }
220 }
221 
222 bool
225 {
226  for (CORBA::ULong i = 0; i < s1.length(); ++i) {
227  for (CORBA::ULong j = 0; j < s2.length(); ++j) {
228  if (0 == std::strcmp(s1[i].transport_type, s2[j].transport_type)) {
229  return true;
230  }
231  }
232  }
233  return false;
234 }
235 
236 bool
241  DDS::DataWriterQos const * const writerQos,
242  DDS::DataReaderQos const * const readerQos,
243  DDS::PublisherQos const * const pubQos,
244  DDS::SubscriberQos const * const subQos)
245 {
246  bool compatible = true;
247 
248  // Check transport-type compatibility
249  if (!compatibleTransports(pubTLS, subTLS)) {
250  compatible = false;
251  increment_incompatibility_count(writerStatus,
253  increment_incompatibility_count(readerStatus,
255  }
256 
257  // Verify compatibility of DataWriterQos and DataReaderQos
258  compatible = compatible && compatibleQOS(writerQos, readerQos,
259  writerStatus, readerStatus);
260 
261  // Verify compatibility of PublisherQos and SubscriberQos
262  compatible = compatible && compatibleQOS(pubQos, subQos,
263  writerStatus, readerStatus);
264 
265  // Verify publisher and subscriber are in a matching partition.
266  //
267  // According to the DDS spec:
268  //
269  // Failure to match partitions is not considered an incompatible
270  // QoS and does not trigger any listeners nor conditions.
271  //
272  // Don't increment the incompatibity count.
273  compatible = compatible && matching_partitions(pubQos->partition,
274  subQos->partition);
275 
276  return compatible;
277 }
278 
279 bool
281  const DDS::SubscriberQos* subQos,
284 {
285  bool compatible = true;
286 
287  // PARTITION, GROUP_DATA, and ENTITY_FACTORY are RxO==no.
288 
289  // Check the PRESENTATION_QOS_POLICY_ID
290  if ((pubQos->presentation.access_scope < subQos->presentation.access_scope)
292  || (!pubQos->presentation.ordered_access && subQos->presentation.ordered_access)) {
293  compatible = false;
294 
295  increment_incompatibility_count(writerStatus,
297  increment_incompatibility_count(readerStatus,
299  }
300 
301  return compatible;
302 }
303 
304 bool
306  const DDS::DataReaderQos * readerQos,
309 {
310  bool compatible = true;
311 
312  // Check the RELIABILITY_QOS_POLICY_ID
313  if (writerQos->reliability.kind < readerQos->reliability.kind) {
314  compatible = false;
315 
316  increment_incompatibility_count(writerStatus,
318  increment_incompatibility_count(readerStatus,
320  }
321 
322  // Check the DURABILITY_QOS_POLICY_ID
323  if (writerQos->durability.kind < readerQos->durability.kind) {
324  compatible = false;
325 
326  increment_incompatibility_count(writerStatus,
328  increment_incompatibility_count(readerStatus,
330  }
331 
332  // Check the LIVELINESS_QOS_POLICY_ID
333  // invalid if offered kind is less than requested kind OR
334  // if offered liveliness duration greater than requested
335  // liveliness duration
336  using OpenDDS::DCPS::operator>;
337  if (writerQos->liveliness.kind < readerQos->liveliness.kind
338  || writerQos->liveliness.lease_duration
339  > readerQos->liveliness.lease_duration) {
340 
341  compatible = false;
342 
343  increment_incompatibility_count(writerStatus,
345  increment_incompatibility_count(readerStatus,
347  }
348 
349  // Check the DEADLINE_QOS_POLICY_ID
350  // Offered deadline must be less than or equal to the requested
351  // deadline.
352  if (writerQos->deadline.period > readerQos->deadline.period) {
353 
354  compatible = false;
355 
356  increment_incompatibility_count(writerStatus,
358  increment_incompatibility_count(readerStatus,
360  }
361 
362  // Check the LATENCY_BUDGET
363  // The reader's duration must be greater than or equal to the writer's
364  using OpenDDS::DCPS::operator<;
365  if (readerQos->latency_budget.duration < writerQos->latency_budget.duration) {
366 
367  compatible = false;
368 
369  increment_incompatibility_count(writerStatus,
371  increment_incompatibility_count(readerStatus,
373  }
374 
375  // The value of the OWNERSHIP kind offered must exactly match the one
376  // requested or else they are considered incompatible.
377  if (writerQos->ownership.kind != readerQos->ownership.kind) {
378  compatible = false;
379 
380  increment_incompatibility_count(writerStatus,
382  increment_incompatibility_count(readerStatus,
384  }
385 
386  {
387  // Find a common data representation
388  bool found = false;
389  const CORBA::ULong reader_count = readerQos->representation.value.length();
390  const CORBA::ULong writer_count = writerQos->representation.value.length();
391  for (CORBA::ULong wi = 0; !found && wi < writer_count; ++wi) {
392  for (CORBA::ULong ri = 0; !found && ri < reader_count; ++ri) {
393  if (readerQos->representation.value[ri] == writerQos->representation.value[wi]) {
394  found = true;
395  break;
396  }
397  }
398  }
399 
400  if (!found) {
401  increment_incompatibility_count(writerStatus,
403  increment_incompatibility_count(readerStatus,
405  compatible = false;
406  }
407  }
408 
409  return compatible;
410 }
411 
412 #ifndef OPENDDS_SAFETY_PROFILE
413 using OpenDDS::DCPS::operator==;
414 #endif
416  const DDS::DataReaderQos & qos2)
417 {
418  return !(
419  (qos1.deadline == qos2.deadline) &&
420  (qos1.latency_budget == qos2.latency_budget));
421 }
422 
424  const DDS::DataWriterQos & qos2)
425 {
426  return !(
427  (qos1.deadline == qos2.deadline) &&
428  (qos1.latency_budget == qos2.latency_budget));
429 }
430 
432  const DDS::SubscriberQos & qos2)
433 {
434  return !(qos1.partition == qos2.partition);
435 }
436 
438  const DDS::PublisherQos & qos2)
439 {
440  return !(qos1.partition == qos2.partition);
441 }
442 
444  const DDS::TopicQos & /*qos2*/)
445 {
446  return false;
447 }
448 
450  const DDS::DomainParticipantQos & /*qos2*/)
451 {
452  return false;
453 }
454 
456 {
457  switch(repr) {
459  kind = Encoding::KIND_XCDR1;
460  break;
462  kind = Encoding::KIND_XCDR2;
463  break;
466  break;
467  default:
468  return false;
469  }
470  return true;
471 }
472 
474 {
475  DCPS::String repr_string;
476  switch (repr) {
478  repr_string = "XCDR_DATA_REPRESENTATION";
479  break;
481  repr_string = "XML_DATA_REPRESENTATION";
482  break;
484  repr_string = "XCDR2_DATA_REPRESENTATION";
485  break;
487  repr_string = "UNALIGNED_CDR_DATA_REPRESENTATION";
488  break;
489  default:
490  repr_string = to_dds_string(repr);
491  }
492  return repr_string;
493 }
494 
496 {
497  DCPS::String repr_string;
498  const ACE_CDR::ULong length = is_data_writer ? 1 : id_seq.length();
499  for (ACE_CDR::ULong i = 0; i < length; ++i) {
500  if (i > 0) {
501  repr_string += ", ";
502  }
503  repr_string += repr_to_string(id_seq[i]);
504  }
505  return repr_string;
506 }
507 
509  bool cdr_encapsulated)
510 {
511  if (qos.length() == 0) {
512  qos.length(1);
514  }
515 }
516 
518 {
519  if (qos.length() == 0) {
520  qos.length(3);
524  }
525 }
526 
527 } // namespace DCPS
528 } // namespace OpenDDS
529 
PartitionQosPolicy partition
const QosPolicyId_t PRESENTATION_QOS_POLICY_ID
bool matches(const PartitionName &n)
Definition: DCPS_Utils.cpp:123
#define ACE_ERROR(X)
const LogLevel::Value value
Definition: debug.cpp:61
size_t strcspn(const char *s, const char *reject)
const ReturnCode_t RETCODE_PRECONDITION_NOT_MET
std::string String
const QosPolicyId_t DEADLINE_QOS_POLICY_ID
const ReturnCode_t RETCODE_INCONSISTENT_POLICY
ReliabilityQosPolicy reliability
OwnershipQosPolicy ownership
DurabilityQosPolicy durability
const QosPolicyId_t DURABILITY_QOS_POLICY_ID
String to_dds_string(unsigned short to_convert)
const ReturnCode_t RETCODE_ALREADY_DELETED
DCPS::String repr_to_string(const DDS::DataRepresentationId_t &repr)
Definition: DCPS_Utils.cpp:473
PresentationQosPolicyAccessScopeKind access_scope
OwnershipQosPolicy ownership
const QosPolicyId_t DATA_REPRESENTATION_QOS_POLICY_ID
LivelinessQosPolicy liveliness
DeadlineQosPolicy deadline
OwnershipQosPolicyKind kind
sequence< TransportLocator > TransportLocatorSeq
bool compatibleQOS(OpenDDS::DCPS::IncompatibleQosStatus *writerStatus, OpenDDS::DCPS::IncompatibleQosStatus *readerStatus, const OpenDDS::DCPS::TransportLocatorSeq &pubTLS, const OpenDDS::DCPS::TransportLocatorSeq &subTLS, DDS::DataWriterQos const *const writerQos, DDS::DataReaderQos const *const readerQos, DDS::PublisherQos const *const pubQos, DDS::SubscriberQos const *const subQos)
Definition: DCPS_Utils.cpp:237
const DataRepresentationId_t XCDR_DATA_REPRESENTATION
DataRepresentationQosPolicy representation
sequence< DataRepresentationId_t > DataRepresentationIdSeq
void set_reader_effective_data_rep_qos(DDS::DataRepresentationIdSeq &qos)
Definition: DCPS_Utils.cpp:517
LatencyBudgetQosPolicy latency_budget
void set_writer_effective_data_rep_qos(DDS::DataRepresentationIdSeq &qos, bool cdr_encapsulated)
Definition: DCPS_Utils.cpp:508
const ReturnCode_t RETCODE_IMMUTABLE_POLICY
const QosPolicyId_t OWNERSHIP_QOS_POLICY_ID
long QosPolicyId_t
Definition: DdsDcpsCore.idl:55
PresentationQosPolicy presentation
const QosPolicyId_t LIVELINESS_QOS_POLICY_ID
const DataRepresentationId_t XCDR2_DATA_REPRESENTATION
ReliabilityQosPolicyKind kind
ACE_CDR::ULong ULong
DurabilityQosPolicyKind kind
DurabilityQosPolicy durability
const ReturnCode_t RETCODE_TIMEOUT
DataRepresentationQosPolicy representation
PartitionName(const char *name)
Definition: DCPS_Utils.cpp:119
const ReturnCode_t RETCODE_OUT_OF_RESOURCES
const ReturnCode_t RETCODE_ILLEGAL_OPERATION
const DataRepresentationId_t XML_DATA_REPRESENTATION
const char * topicstatus_to_string(TopicStatus value)
Definition: DCPS_Utils.cpp:70
ACE_UINT32 ULong
const DDS::DataRepresentationId_t UNALIGNED_CDR_DATA_REPRESENTATION
int strcmp(const char *s, const char *t)
const char *const name
Definition: debug.cpp:60
void increment_incompatibility_count(OpenDDS::DCPS::IncompatibleQosStatus *status, DDS::QosPolicyId_t incompatible_policy)
Definition: DCPS_Utils.cpp:194
bool compatibleTransports(const OpenDDS::DCPS::TransportLocatorSeq &s1, const OpenDDS::DCPS::TransportLocatorSeq &s2)
Definition: DCPS_Utils.cpp:223
ACE_TEXT("TCP_Factory")
DCPS::String repr_seq_to_string(const DDS::DataRepresentationIdSeq &id_seq, bool is_data_writer)
Definition: DCPS_Utils.cpp:495
const QosPolicyId_t LATENCYBUDGET_QOS_POLICY_ID
const ReturnCode_t RETCODE_NOT_ENABLED
const ReturnCode_t RETCODE_NO_DATA
QosPolicyId_t policy_id
Definition: DdsDcpsCore.idl:58
ReliabilityQosPolicy reliability
bool repr_to_encoding_kind(DDS::DataRepresentationId_t repr, Encoding::Kind &kind)
Definition: DCPS_Utils.cpp:455
const char * retcode_to_string(DDS::ReturnCode_t value)
Definition: DCPS_Utils.cpp:29
const ReturnCode_t RETCODE_ERROR
bool matches_name(const DDS::PartitionQosPolicy &qos, const PartitionName &name)
Definition: DCPS_Utils.cpp:143
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
bool matches_default(const DDS::PartitionQosPolicy &qos)
Definition: DCPS_Utils.cpp:156
const ReturnCode_t RETCODE_OK
const ReturnCode_t RETCODE_UNSUPPORTED
bool is_wildcard(const char *str)
Definition: DCPS_Utils.cpp:100
const ReturnCode_t RETCODE_NOT_ALLOWED_BY_SECURITY
LivelinessQosPolicyKind kind
const QosPolicyId_t RELIABILITY_QOS_POLICY_ID
bool should_check_association_upon_change(const DDS::DataReaderQos &qos1, const DDS::DataReaderQos &qos2)
Definition: DCPS_Utils.cpp:415
LivelinessQosPolicy liveliness
short DataRepresentationId_t
DataRepresentationIdSeq value
const ::DDS::QosPolicyId_t TRANSPORTTYPE_QOS_POLICY_ID
DeadlineQosPolicy deadline
LM_ERROR
PartitionQosPolicy partition
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
bool wild_match(const char *s, const char *pattern, bool case_sensitive=true, bool character_classes=false)
PresentationQosPolicy presentation
bool matching_partitions(const DDS::PartitionQosPolicy &pub, const DDS::PartitionQosPolicy &sub)
Definition: DCPS_Utils.cpp:170
LatencyBudgetQosPolicy latency_budget
const ReturnCode_t RETCODE_BAD_PARAMETER