diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 4bedb15..a12331b 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -295,5 +295,6 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic = { .to_ser_unref = serdata_builtin_to_ser_unref, .to_topicless = serdata_builtin_to_topicless, .topicless_to_sample = serdata_builtin_topicless_to_sample, - .print = serdata_builtin_topic_print + .print = serdata_builtin_topic_print, + .get_keyhash = 0 }; diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index e020735..4896120 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -1579,7 +1579,10 @@ void dds_stream_extract_keyhash (dds_istream_t * __restrict is, dds_keyhash_t * const dds_topic_descriptor_t *desc = topic->type; kh->m_set = 1; if (desc->m_nkeys == 0) + { kh->m_iskey = 1; + kh->m_keysize = 0; + } else if (desc->m_flagset & DDS_TOPIC_FIXED_KEY) { dds_ostreamBE_t os; @@ -1592,12 +1595,14 @@ void dds_stream_extract_keyhash (dds_istream_t * __restrict is, dds_keyhash_t * else dds_stream_extract_keyBE_from_data (is, &os, topic); assert (os.x.m_index <= 16); + kh->m_keysize = (unsigned)os.x.m_index & 0x1f; } else { dds_ostreamBE_t os; ddsrt_md5_state_t md5st; kh->m_iskey = 0; + kh->m_keysize = 16; dds_ostreamBE_init (&os, 0); if (just_key) dds_stream_extract_keyBE_from_key (is, &os, topic); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h index 4d9b64b..61a57e8 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h @@ -132,6 +132,11 @@ typedef bool (*ddsi_serdata_eqkey_t) (const struct ddsi_serdata *a, const struct returning bufsize-1) if it had to truncate) */ typedef size_t (*ddsi_serdata_print_t) (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size); +/* Add keyhash (from serdata) to buffer (forcing md5 when necessary). + - key needs to be set within serdata (can already be md5) + - buf needs to be at least 16 bytes large */ +typedef void (*ddsi_serdata_get_keyhash_t) (const struct ddsi_serdata *d, struct nn_keyhash *buf, bool force_md5); + struct ddsi_serdata_ops { ddsi_serdata_eqkey_t eqkey; ddsi_serdata_size_t get_size; @@ -146,9 +151,11 @@ struct ddsi_serdata_ops { ddsi_serdata_topicless_to_sample_t topicless_to_sample; ddsi_serdata_free_t free; ddsi_serdata_print_t print; + ddsi_serdata_get_keyhash_t get_keyhash; }; #define DDSI_SERDATA_HAS_PRINT 1 +#define DDSI_SERDATA_HAS_ADD_KEYHASH 1 DDS_EXPORT void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertopic *tp, enum ddsi_serdata_kind kind); @@ -221,6 +228,10 @@ DDS_EXPORT inline bool ddsi_serdata_print_topicless (const struct ddsi_sertopic } } +DDS_EXPORT inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct nn_keyhash *buf, bool force_md5) { + d->ops->get_keyhash (d, buf, force_md5); +} + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h index ae582ff..daa8a7b 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -47,6 +47,7 @@ typedef struct dds_keyhash { unsigned char m_hash [16]; /* Key hash value. Also possibly key. Suitably aligned for accessing as uint32_t's */ unsigned m_set : 1; /* has it been initialised? */ unsigned m_iskey : 1; /* m_hash is key value */ + unsigned m_keysize : 5; /* size of the key within the hash buffer */ } dds_keyhash_t; /* Debug builds may want to keep some additional state */ diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 77545d4..b7225fc 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -251,6 +251,7 @@ struct writer unsigned reliable: 1; /* iff 1, writer is reliable <=> heartbeat_xevent != NULL */ unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */ unsigned include_keyhash: 1; /* iff 1, this writer includes a keyhash; keyless topics => include_keyhash = 0 */ + unsigned force_md5_keyhash: 1; /* iff 1, when keyhash has to be hashed, no matter the size */ unsigned retransmitting: 1; /* iff 1, this writer is currently retransmitting */ #ifdef DDSI_INCLUDE_SSM unsigned supports_ssm: 1; diff --git a/src/core/ddsi/include/dds/ddsi/q_xmsg.h b/src/core/ddsi/include/dds/ddsi/q_xmsg.h index 24f32b0..eb99196 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -129,7 +129,7 @@ void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, Sub void nn_xmsg_add_timestamp (struct nn_xmsg *m, nn_wctime_t t); void nn_xmsg_add_entityid (struct nn_xmsg * m); void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len); -void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata); +void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata, bool force_md5); void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo); void nn_xmsg_addpar_sentinel (struct nn_xmsg *m); int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg *m); diff --git a/src/core/ddsi/src/ddsi_serdata.c b/src/core/ddsi/src/ddsi_serdata.c index 68caae0..33d9584 100644 --- a/src/core/ddsi/src/ddsi_serdata.c +++ b/src/core/ddsi/src/ddsi_serdata.c @@ -47,3 +47,4 @@ extern inline bool ddsi_serdata_topicless_to_sample (const struct ddsi_sertopic extern inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const struct ddsi_serdata *b); extern inline bool ddsi_serdata_print (const struct ddsi_serdata *d, char *buf, size_t size); extern inline bool ddsi_serdata_print_topicless (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size); +extern inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct nn_keyhash *buf, bool force_md5); diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 666e0d3..34f88e9 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -231,6 +231,7 @@ static void serdata_default_init(struct ddsi_serdata_default *d, const struct dd memset (d->keyhash.m_hash, 0, sizeof (d->keyhash.m_hash)); d->keyhash.m_set = 0; d->keyhash.m_iskey = 0; + d->keyhash.m_keysize = 0; } static struct ddsi_serdata_default *serdata_default_allocnew (struct serdatapool *serpool, uint32_t init_size) @@ -355,6 +356,7 @@ static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_ser memcpy (d->keyhash.m_hash, keyhash->value, sizeof (d->keyhash.m_hash)); d->keyhash.m_set = 1; d->keyhash.m_iskey = 1; + d->keyhash.m_keysize = sizeof (d->keyhash.m_hash); return fix_serdata_default(d, tp->c.serdata_basehash); } } @@ -368,6 +370,7 @@ static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct dd (void)keyhash; d->keyhash.m_set = 1; d->keyhash.m_iskey = 1; + d->keyhash.m_keysize = 0; return fix_serdata_default_nokey(d, tp->c.serdata_basehash); } @@ -376,11 +379,15 @@ static void gen_keyhash_from_sample (const struct ddsi_sertopic_default *topic, const struct dds_topic_descriptor *desc = (const struct dds_topic_descriptor *) topic->type; kh->m_set = 1; if (desc->m_nkeys == 0) + { kh->m_iskey = 1; + kh->m_keysize = 0; + } else if (desc->m_flagset & DDS_TOPIC_FIXED_KEY) { dds_ostreamBE_t os; kh->m_iskey = 1; + kh->m_keysize = sizeof(kh->m_hash); dds_ostreamBE_init (&os, 0); os.x.m_buffer = kh->m_hash; os.x.m_size = 16; @@ -391,6 +398,7 @@ static void gen_keyhash_from_sample (const struct ddsi_sertopic_default *topic, dds_ostreamBE_t os; ddsrt_md5_state_t md5st; kh->m_iskey = 0; + kh->m_keysize = sizeof(kh->m_hash); dds_ostreamBE_init (&os, 64); dds_stream_write_keyBE (&os, sample, topic); ddsrt_md5_init (&md5st); @@ -461,6 +469,7 @@ static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi case PID_GROUP_GUID: d->keyhash.m_set = 1; d->keyhash.m_iskey = 1; + d->keyhash.m_keysize = sizeof(d->keyhash.m_hash); memcpy (d->keyhash.m_hash, rawkey, 16); #ifndef NDEBUG keysize = 16; @@ -477,6 +486,7 @@ static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi topic_name_sz_BE = ddsrt_toBE4u (topic_name_sz); d->keyhash.m_set = 1; d->keyhash.m_iskey = 0; + d->keyhash.m_keysize = sizeof(d->keyhash.m_hash); ddsrt_md5_init (&md5st); ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) &topic_name_sz_BE, sizeof (topic_name_sz_BE)); ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) topic_name, topic_name_sz); @@ -512,10 +522,14 @@ static struct ddsi_serdata *serdata_default_from_sample_rawcdr (const struct dds d->keyhash.m_set = 1; d->keyhash.m_iskey = 1; if (sample->keysize == 0) + { + d->keyhash.m_keysize = 0; return fix_serdata_default_nokey (d, tp->c.serdata_basehash); + } else { memcpy (&d->keyhash.m_hash, sample->key, sample->keysize); + d->keyhash.m_keysize = (unsigned)sample->keysize & 0x1f; return fix_serdata_default (d, tp->c.serdata_basehash); } } @@ -656,6 +670,24 @@ static size_t serdata_default_print_raw (const struct ddsi_sertopic *sertopic_co return (size_t) snprintf (buf, size, "(blob)"); } +static void serdata_default_get_keyhash (const struct ddsi_serdata *serdata_common, struct nn_keyhash *buf, bool force_md5) +{ + const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; + assert(buf); + assert(d->keyhash.m_set); + if (force_md5 && d->keyhash.m_iskey /* m_iskey == !md5 */) + { + ddsrt_md5_state_t md5st; + ddsrt_md5_init (&md5st); + ddsrt_md5_append(&md5st, (ddsrt_md5_byte_t*)(d->keyhash.m_hash), d->keyhash.m_keysize); + ddsrt_md5_finish(&md5st, (ddsrt_md5_byte_t*)(buf->value)); + } + else + { + memcpy (buf->value, d->keyhash.m_hash, 16); + } +} + const struct ddsi_serdata_ops ddsi_serdata_ops_cdr = { .get_size = serdata_default_get_size, .eqkey = serdata_default_eqkey, @@ -669,7 +701,8 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_cdr = { .to_ser_unref = serdata_default_to_ser_unref, .to_topicless = serdata_default_to_topicless, .topicless_to_sample = serdata_default_topicless_to_sample_cdr, - .print = serdata_default_print_cdr + .print = serdata_default_print_cdr, + .get_keyhash = serdata_default_get_keyhash }; const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey = { @@ -685,7 +718,8 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey = { .to_ser_unref = serdata_default_to_ser_unref, .to_topicless = serdata_default_to_topicless, .topicless_to_sample = serdata_default_topicless_to_sample_cdr_nokey, - .print = serdata_default_print_cdr + .print = serdata_default_print_cdr, + .get_keyhash = serdata_default_get_keyhash }; const struct ddsi_serdata_ops ddsi_serdata_ops_plist = { @@ -701,7 +735,8 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_plist = { .to_ser_unref = serdata_default_to_ser_unref, .to_topicless = serdata_default_to_topicless, .topicless_to_sample = 0, - .print = serdata_default_print_plist + .print = serdata_default_print_plist, + .get_keyhash = serdata_default_get_keyhash }; const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr = { @@ -717,5 +752,6 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr = { .to_ser_unref = serdata_default_to_ser_unref, .to_topicless = serdata_default_to_topicless, .topicless_to_sample = 0, - .print = serdata_default_print_raw + .print = serdata_default_print_raw, + .get_keyhash = serdata_default_get_keyhash }; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 3a5b98a..3806294 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3063,6 +3063,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->throttle_tracing = 0; wr->rexmit_count = 0; wr->rexmit_lost_count = 0; + wr->force_md5_keyhash = 0; wr->status_cb = status_cb; wr->status_cb_entity = status_entity; diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 032b638..7e08483 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -492,7 +492,7 @@ static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t s /* Adding parameters means potential reallocing, so sm, ddcmn now likely become invalid */ if (wr->include_keyhash) - nn_xmsg_addpar_keyhash (*pmsg, serdata); + nn_xmsg_addpar_keyhash (*pmsg, serdata, wr->force_md5_keyhash); if (serdata->statusinfo) nn_xmsg_addpar_statusinfo (*pmsg, serdata->statusinfo); if (nn_xmsg_addpar_sentinel_ifparam (*pmsg) > 0) @@ -659,7 +659,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru /* Adding parameters means potential reallocing, so sm, ddcmn now likely become invalid */ if (wr->include_keyhash) { - nn_xmsg_addpar_keyhash (*pmsg, serdata); + nn_xmsg_addpar_keyhash (*pmsg, serdata, wr->force_md5_keyhash); } if (serdata->statusinfo) { diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index b8cbbb6..b0aad86 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -938,13 +938,12 @@ void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len) return p; } -void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata) +void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata, bool force_md5) { if (serdata->kind != SDK_EMPTY) { - const struct ddsi_serdata_default *serdata_def = (const struct ddsi_serdata_default *)serdata; char *p = nn_xmsg_addpar (m, PID_KEYHASH, 16); - memcpy (p, serdata_def->keyhash.m_hash, 16); + ddsi_serdata_get_keyhash(serdata, (struct nn_keyhash*)p, force_md5); } }