diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index 4a9d6f3..516adbc 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -243,6 +243,9 @@ struct nn_rdata; DDS_EXPORT unsigned char *nn_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const nn_plist_src_t *src); DDS_EXPORT const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid); +DDS_EXPORT void nn_free_property_policy (dds_property_qospolicy_t *property); +DDS_EXPORT void nn_duplicate_property (dds_property_t *dest, const dds_property_t *src); + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_xqos.h b/src/core/ddsi/include/dds/ddsi/q_xqos.h index 7ae7a02..28fe888 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/q_xqos.h @@ -32,6 +32,39 @@ typedef ddsi_octetseq_t dds_userdata_qospolicy_t; typedef ddsi_octetseq_t dds_topicdata_qospolicy_t; typedef ddsi_octetseq_t dds_groupdata_qospolicy_t; +typedef struct dds_property { + /* The propagate boolean will not be send over the wire. + * When the value is 'false', the complete struct shouldn't be send. + * It has to be the first variable within the structure. */ + unsigned char propagate; + char *name; + char *value; +} dds_property_t; + +typedef struct dds_propertyseq { + uint32_t n; + dds_property_t *props; +} dds_propertyseq_t; + +typedef struct dds_binaryproperty { + /* The propagate boolean will not be send over the wire. + * When the value is 'false', the complete struct shouldn't be send. + * It has to be the first variable within the structure. */ + unsigned char propagate; + char *name; + ddsi_octetseq_t value; +} dds_binaryproperty_t; + +typedef struct dds_binarypropertyseq { + uint32_t n; + dds_binaryproperty_t *props; +} dds_binarypropertyseq_t; + +typedef struct dds_property_qospolicy { + dds_propertyseq_t value; + dds_binarypropertyseq_t binary_value; +} dds_property_qospolicy_t; + typedef struct dds_durability_qospolicy { dds_durability_kind_t kind; } dds_durability_qospolicy_t; @@ -212,6 +245,7 @@ typedef struct dds_ignorelocal_qospolicy { #define QP_PRISMTECH_SUBSCRIPTION_KEYS ((uint64_t)1 << 25) #define QP_PRISMTECH_ENTITY_FACTORY ((uint64_t)1 << 27) #define QP_CYCLONE_IGNORELOCAL ((uint64_t)1 << 30) +#define QP_PROPERTY_LIST ((uint64_t)1 << 31) /* Partition QoS is not RxO according to the specification (DDS 1.2, section 7.1.3), but communication will not take place unless it @@ -263,6 +297,7 @@ struct dds_qos { /*x xR*/dds_subscription_keys_qospolicy_t subscription_keys; /*x xR*/dds_reader_lifespan_qospolicy_t reader_lifespan; /* x */dds_ignorelocal_qospolicy_t ignorelocal; + /*xxx */dds_property_qospolicy_t property; }; struct nn_xmsg; diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 622b0e2..39879f4 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -453,6 +453,7 @@ static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi #ifndef NDEBUG size_t keysize; #endif + assert(rawkey); switch (sample->keyparam) { case PID_PARTICIPANT_GUID: diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 5e3a403..14fd786 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -115,10 +115,10 @@ struct piddesc { size_t plist_offset; /* offset from start of nn_plist_t */ size_t size; /* in-memory size for copying */ union { - /* descriptor for generic code: 4 is enough for the current set of + /* descriptor for generic code: 11 is enough for the current set of parameters, compiler will warn if one ever tries to use more than will fit; on non-GCC/Clang and 32-bits machines */ - const enum pserop desc[5]; + const enum pserop desc[11]; struct { dds_return_t (*deser) (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff); dds_return_t (*ser) (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff); @@ -357,7 +357,6 @@ static size_t ser_generic_srcsize (const enum pserop * __restrict desc) desc++; } #undef SIMPLE -#undef COMPLEX } static void fini_generic_partial (void * __restrict dst, size_t * __restrict dstoff, const enum pserop *desc, const enum pserop * const desc_end, bool aliased) @@ -393,9 +392,8 @@ static void fini_generic_partial (void * __restrict dst, size_t * __restrict dst /* non-nested, so never a need to deallocate only some of the entries and no complications in locating the end of the sequence element description */ COMPLEX (XQ, ddsi_octetseq_t, { - const size_t elem_size = ser_generic_srcsize (desc + 1); + size_t elem_off = 0; for (uint32_t i = 0; i < x->length; i++) { - size_t elem_off = i * elem_size; fini_generic_partial (x->value, &elem_off, desc + 1, desc_end, aliased); } }, ddsrt_free (x->value)); @@ -542,10 +540,10 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds if (deser_uint32 (&x->length, dd, srcoff) < 0 || x->length > dd->bufsz - *srcoff) goto fail; const size_t elem_size = ser_generic_srcsize (desc + 1); + size_t elem_off = 0; x->value = x->length ? ddsrt_malloc (x->length * elem_size) : NULL; for (uint32_t i = 0; i < x->length; i++) { - size_t elem_off = i * elem_size; if (deser_generic (x->value, &elem_off, flagset, flag, dd, srcoff, desc + 1) < 0) goto fail; } @@ -564,7 +562,7 @@ fail: return DDS_RETCODE_BAD_PARAMETER; } -static void ser_generic_size1 (size_t *dstoff, const void *src, size_t srcoff, const enum pserop * __restrict desc) +static void ser_generic_size_partial (size_t *dstoff, const void *src, size_t srcoff, const enum pserop * __restrict desc) { bool suppressed = false; #define COMPLEX(basecase_, type_, dstoff_update_) do { \ @@ -598,19 +596,20 @@ static void ser_generic_size1 (size_t *dstoff, const void *src, size_t srcoff, c const size_t elem_size = ser_generic_srcsize (desc + 1); *dstoff = align4size (*dstoff) + 4; for (uint32_t i = 0; i < x->length; i++) - ser_generic_size1 (dstoff, x->value, i * elem_size, desc + 1); + ser_generic_size_partial (dstoff, x->value, i * elem_size, desc + 1); }); while (*++desc != XSTOP) { } break; } desc++; } -#undef SIMPLE +#undef SIMPLE4 +#undef SIMPLE1 #undef COMPLEX } static size_t ser_generic_size (const void *src, size_t srcoff, const enum pserop * __restrict desc) { size_t dstoff = 0; - ser_generic_size1 (&dstoff, src, srcoff, desc); + ser_generic_size_partial (&dstoff, src, srcoff, desc); return dstoff; } @@ -629,7 +628,7 @@ static uint32_t ser_generic_count (const ddsi_octetseq_t *src, size_t elem_size, return count; } -static dds_return_t ser_generic1 (char * const data, size_t *dstoff, const void *src, size_t srcoff, const enum pserop * __restrict desc) +static dds_return_t ser_generic_partial (char * const data, size_t *dstoff, const void *src, size_t srcoff, const enum pserop * __restrict desc) { while (true) { @@ -750,7 +749,7 @@ static dds_return_t ser_generic1 (char * const data, size_t *dstoff, const void const size_t elem_size = ser_generic_srcsize (desc + 1); *((uint32_t *) p) = ser_generic_count (x, elem_size, desc + 1); for (uint32_t i = 0; i < x->length; i++) - ser_generic1 (data, dstoff, x->value, i * elem_size, desc + 1); + ser_generic_partial (data, dstoff, x->value, i * elem_size, desc + 1); } srcoff += sizeof (*x); while (*++desc != XSTOP) { } @@ -765,7 +764,7 @@ static dds_return_t ser_generic (struct nn_xmsg *xmsg, nn_parameterid_t pid, con { char * const data = nn_xmsg_addpar (xmsg, pid, ser_generic_size (src, srcoff, desc)); size_t dstoff = 0; - return ser_generic1 (data, &dstoff, src, srcoff, desc); + return ser_generic_partial (data, &dstoff, src, srcoff, desc); } static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict dstoff, const enum pserop * __restrict desc) @@ -796,10 +795,9 @@ static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict case XG: SIMPLE (XG, ddsi_guid_t); break; case XK: SIMPLE (XK, nn_keyhash_t); break; case XQ: COMPLEX (XQ, ddsi_octetseq_t, if (x->length) { - const size_t elem_size = ser_generic_srcsize (desc + 1); - x->value = ddsrt_memdup (x->value, x->length * elem_size); + size_t elem_off = 0; + x->value = ddsrt_memdup (x->value, x->length * ser_generic_srcsize(desc + 1)); for (uint32_t i = 0; i < x->length; i++) { - size_t elem_off = i * elem_size; unalias_generic (x->value, &elem_off, desc + 1); } }); while (*++desc != XSTOP) { } break; @@ -1029,6 +1027,15 @@ static dds_return_t dvx_reader_favours_ssm (void * __restrict dst, const struct } #endif +/* pserop representation of dds_propertyseq_t. */ +#define PROPERTYSEQ_PSEROP XQ, XbPROP, XS, XS, XSTOP + +/* pserop representation of dds_binarypropertyseq_t. */ +#define BINPROPERTYSEQ_PSEROP XQ, XbPROP, XS, XO, XSTOP + +/* pserop representation of dds_property_qospolicy_t. */ +#define PROPERTY_POLICY_PSEROP PROPERTYSEQ_PSEROP, BINPROPERTYSEQ_PSEROP + /* Standardized parameters -- QoS _MUST_ come first (nn_plist_init_tables verifies this) because it allows early-out when processing a dds_qos_t instead of an nn_plist_t */ static const struct piddesc piddesc_omg[] = { @@ -1044,6 +1051,7 @@ static const struct piddesc piddesc_omg[] = { QP (DEADLINE, deadline, XD), QP (LATENCY_BUDGET, latency_budget, XD), QP (LIVELINESS, liveliness, XE2, XD), + QP (PROPERTY_LIST, property, PROPERTY_POLICY_PSEROP), /* Reliability encoding does not follow the rules (best-effort/reliable map to 1/2 instead of 0/1 */ { PID_RELIABILITY, PDF_QOS | PDF_FUNCTION, QP_RELIABILITY, "RELIABILITY", offsetof (struct nn_plist, qos.reliability), membersize (struct nn_plist, qos.reliability), @@ -1219,8 +1227,8 @@ static const struct piddesc_index piddesc_vendor_index[] = { /* List of entries that require unalias, fini processing; initialized by nn_plist_init_tables; will assert when table too small or too large */ -static const struct piddesc *piddesc_unalias[18]; -static const struct piddesc *piddesc_fini[18]; +static const struct piddesc *piddesc_unalias[19]; +static const struct piddesc *piddesc_fini[19]; static ddsrt_once_t table_init_control = DDSRT_ONCE_INIT; static nn_parameterid_t pid_without_flags (nn_parameterid_t pid) @@ -2306,7 +2314,7 @@ const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_pa const nn_parameter_t *par = src; while (par->parameterid != pid) { - if (pid == PID_SENTINEL) + if (par->parameterid == PID_SENTINEL) return NULL; par = (const nn_parameter_t *) ((const char *) (par + 1) + par->length); } @@ -2841,6 +2849,29 @@ void nn_log_xqos (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qo }); DO (PRISMTECH_ENTITY_FACTORY, { LOGB1 ("entity_factory=%u", xqos->entity_factory.autoenable_created_entities); }); DO (CYCLONE_IGNORELOCAL, { LOGB1 ("ignorelocal=%u", xqos->ignorelocal.value); }); + DO (PROPERTY_LIST, { + LOGB0 ("property_list={"); + DDS_CLOG (cat, logcfg, "value={"); + for (uint32_t i = 0; i < xqos->property.value.n; i++) { + DDS_CLOG (cat, logcfg, "%s{%s,%s,%u}", + (i == 0) ? "" : ",", + xqos->property.value.props[i].name, + xqos->property.value.props[i].value, + xqos->property.value.props[i].propagate); + } + DDS_CLOG (cat, logcfg, "}"); + DDS_CLOG (cat, logcfg, "binary_value={"); + for (uint32_t i = 0; i < xqos->property.binary_value.n; i++) { + DDS_CLOG (cat, logcfg, "%s{%s,(%u,%p),%u}", + (i == 0) ? "" : ",", + xqos->property.binary_value.props[i].name, + xqos->property.binary_value.props[i].value.length, + xqos->property.binary_value.props[i].value.value, + xqos->property.binary_value.props[i].propagate); + } + DDS_CLOG (cat, logcfg, "}"); + DDS_CLOG (cat, logcfg, "}"); + }); #undef PRINTARG_DUR #undef FMT_DUR @@ -2852,3 +2883,29 @@ void nn_log_xqos (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qo #undef LOGB1 #undef LOGB0 } + +void nn_free_property_policy(dds_property_qospolicy_t *property) +{ + const struct piddesc_index *index = &piddesc_vendor_index[0]; + const struct piddesc *entry = index->index[PID_PROPERTY_LIST]; + size_t niloff = 0; + fini_generic_partial ((void*)property, &niloff, entry->op.desc, NULL, true); +} + +void nn_duplicate_property (dds_property_t *dest, const dds_property_t *src) +{ + const struct piddesc_index *index = &piddesc_vendor_index[0]; + const struct piddesc *entry = index->index[PID_PROPERTY_LIST]; + dds_property_qospolicy_t policy; + size_t niloff = 0; + /* First, do a shallow copy. */ + *dest = *src; + /* Unalias the shallow copy to get a deep copy. */ + policy.value.n = 1; + policy.value.props = dest; + policy.binary_value.n = 0; + policy.binary_value.props = NULL; + (void)unalias_generic(&policy, &niloff, entry->op.desc); + /* Shallow copy the deep copy. */ + *dest = *policy.value.props; +}