Participant generic message (#273)
* Extended DDSI (de)serializer. Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com> * Added security Participant Generic Message. Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com> * Updated Participant Generic Message. Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com> * Updated generic ddsi (de)serializer. Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com> * Changed macros for functions. Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>
This commit is contained in:
		
							parent
							
								
									7c1e47218d
								
							
						
					
					
						commit
						64cc631137
					
				
					 10 changed files with 881 additions and 94 deletions
				
			
		| 
						 | 
				
			
			@ -123,6 +123,17 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
 | 
			
		|||
target_sources(ddsc
 | 
			
		||||
  PRIVATE ${srcs_ddsi} ${hdrs_private_ddsi})
 | 
			
		||||
 | 
			
		||||
if(ENABLE_SECURITY)
 | 
			
		||||
  PREPEND(security_srcs "${CMAKE_CURRENT_LIST_DIR}/src"
 | 
			
		||||
          ddsi_security_msg.c)
 | 
			
		||||
 | 
			
		||||
  PREPEND(security_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
 | 
			
		||||
          ddsi_security_msg.h)
 | 
			
		||||
 | 
			
		||||
  target_sources(ddsc
 | 
			
		||||
    PRIVATE ${security_srcs} ${security_hdrs})
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
target_include_directories(ddsc
 | 
			
		||||
  PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ enum pserop {
 | 
			
		|||
  Xi, Xix2, Xix3, Xix4, /* int32_t, 1 .. 4 in a row */
 | 
			
		||||
  Xu, Xux2, Xux3, Xux4, Xux5, /* uint32_t, 1 .. 5 in a row */
 | 
			
		||||
  XD, XDx2, /* duration, 1 .. 2 in a row */
 | 
			
		||||
  Xl,       /* int64_t */
 | 
			
		||||
  Xo, Xox2, /* octet, 1 .. 2 in a row */
 | 
			
		||||
  Xb, Xbx2, /* boolean, 1 .. 2 in a row */
 | 
			
		||||
  XbCOND, /* boolean: compare to ignore remainder if false (for use_... flags) */
 | 
			
		||||
| 
						 | 
				
			
			@ -44,15 +45,6 @@ enum pserop {
 | 
			
		|||
  Xopt, /* remainder is optional on deser, 0-init if not present */
 | 
			
		||||
} ddsrt_attribute_packed;
 | 
			
		||||
 | 
			
		||||
inline bool pserop_seralign_is_1 (enum pserop op) {
 | 
			
		||||
  /* NB: XbPROP is never serialized, so its alignment is irrelevant.  If ever there
 | 
			
		||||
     is a need to allow calling this function when op = XbPROP, it needs to be changed
 | 
			
		||||
     to taking the address of the pserop, and in that case inspect the following
 | 
			
		||||
     operator */
 | 
			
		||||
  assert (op != XbPROP && op != Xopt && op != XSTOP);
 | 
			
		||||
  return (op >= Xo && op <= XK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT void plist_fini_generic (void * __restrict dst, const enum pserop *desc, bool aliased);
 | 
			
		||||
DDS_EXPORT dds_return_t plist_deser_generic (void * __restrict dst, const void * __restrict src, size_t srcsize, bool bswap, const enum pserop * __restrict desc);
 | 
			
		||||
DDS_EXPORT dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										91
									
								
								src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,91 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
 | 
			
		||||
 *
 | 
			
		||||
 * This program and the accompanying materials are made available under the
 | 
			
		||||
 * terms of the Eclipse Public License v. 2.0 which is available at
 | 
			
		||||
 * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
 | 
			
		||||
 * v. 1.0 which is available at
 | 
			
		||||
 * http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 | 
			
		||||
 */
 | 
			
		||||
#ifndef DDSI_SECURITY_MSG_H
 | 
			
		||||
#define DDSI_SECURITY_MSG_H
 | 
			
		||||
 | 
			
		||||
#include "dds/ddsi/q_plist.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_guid.h"
 | 
			
		||||
#include "dds/ddsrt/retcode.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_plist_generic.h"
 | 
			
		||||
 | 
			
		||||
#if defined (__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define GMCLASSID_SECURITY_AUTH_REQUEST       "dds.sec.auth_request"
 | 
			
		||||
#define GMCLASSID_SECURITY_AUTH_HANDSHAKE     "dds.sec.auth"
 | 
			
		||||
 | 
			
		||||
typedef struct nn_message_identity {
 | 
			
		||||
  ddsi_guid_t source_guid;
 | 
			
		||||
  int64_t sequence_number;
 | 
			
		||||
} nn_message_identity_t;
 | 
			
		||||
 | 
			
		||||
typedef struct nn_participant_generic_message {
 | 
			
		||||
  nn_message_identity_t message_identity;
 | 
			
		||||
  nn_message_identity_t related_message_identity;
 | 
			
		||||
  ddsi_guid_t destinaton_participant_guid;
 | 
			
		||||
  ddsi_guid_t destination_endpoint_guid;
 | 
			
		||||
  ddsi_guid_t source_endpoint_guid;
 | 
			
		||||
  const char *message_class_id;
 | 
			
		||||
  nn_dataholderseq_t message_data;
 | 
			
		||||
} nn_participant_generic_message_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The arguments are aliased in the resulting message structure.
 | 
			
		||||
 * This means that the lifecycle of the arguments should be longer
 | 
			
		||||
 * then that of the message.
 | 
			
		||||
 */
 | 
			
		||||
DDS_EXPORT void
 | 
			
		||||
nn_participant_generic_message_init(
 | 
			
		||||
   nn_participant_generic_message_t *msg,
 | 
			
		||||
   const ddsi_guid_t *wrguid,
 | 
			
		||||
   int64_t wrseq,
 | 
			
		||||
   const ddsi_guid_t *dstpguid,
 | 
			
		||||
   const ddsi_guid_t *dsteguid,
 | 
			
		||||
   const ddsi_guid_t *srceguid,
 | 
			
		||||
   const char *classid,
 | 
			
		||||
   const nn_dataholderseq_t *mdata,
 | 
			
		||||
   const nn_message_identity_t *rmid);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Aliased struct variables will not be freed.
 | 
			
		||||
 */
 | 
			
		||||
DDS_EXPORT void
 | 
			
		||||
nn_participant_generic_message_deinit(
 | 
			
		||||
   nn_participant_generic_message_t *msg);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Some struct variables are aliased to the given buffer.
 | 
			
		||||
 * This means that the lifecycle of the data buffer should be
 | 
			
		||||
 * longer then that of the message.
 | 
			
		||||
 */
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
nn_participant_generic_message_deseralize(
 | 
			
		||||
   nn_participant_generic_message_t *msg,
 | 
			
		||||
   const unsigned char *data,
 | 
			
		||||
   size_t len,
 | 
			
		||||
   bool bswap);
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT dds_return_t
 | 
			
		||||
nn_participant_generic_message_serialize(
 | 
			
		||||
   const nn_participant_generic_message_t *msg,
 | 
			
		||||
   unsigned char **data,
 | 
			
		||||
   size_t *len);
 | 
			
		||||
 | 
			
		||||
DDS_EXPORT extern const enum pserop pserop_participant_generic_message[];
 | 
			
		||||
 | 
			
		||||
#if defined (__cplusplus)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* DDSI_SECURITY_MSG_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -134,6 +134,11 @@ typedef struct nn_dataholder
 | 
			
		|||
  dds_binarypropertyseq_t binary_properties;
 | 
			
		||||
} nn_dataholder_t;
 | 
			
		||||
 | 
			
		||||
typedef struct nn_dataholderseq {
 | 
			
		||||
  uint32_t n;
 | 
			
		||||
  nn_dataholder_t *tags;
 | 
			
		||||
} nn_dataholderseq_t;
 | 
			
		||||
 | 
			
		||||
typedef nn_dataholder_t nn_token_t;
 | 
			
		||||
 | 
			
		||||
/* Used for both nn_participant_security_info and nn_endpoint_security_info. */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										149
									
								
								src/core/ddsi/src/ddsi_security_msg.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/core/ddsi/src/ddsi_security_msg.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,149 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
 | 
			
		||||
 *
 | 
			
		||||
 * This program and the accompanying materials are made available under the
 | 
			
		||||
 * terms of the Eclipse Public License v. 2.0 which is available at
 | 
			
		||||
 * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
 | 
			
		||||
 * v. 1.0 which is available at
 | 
			
		||||
 * http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 | 
			
		||||
 */
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "dds/ddsrt/heap.h"
 | 
			
		||||
#include "dds/ddsrt/string.h"
 | 
			
		||||
#include "dds/ddsi/q_bswap.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_security_msg.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_plist_generic.h"
 | 
			
		||||
 | 
			
		||||
const enum pserop pserop_participant_generic_message[] =
 | 
			
		||||
{
 | 
			
		||||
  /* nn_participant_generic_message */
 | 
			
		||||
  XG, Xl,              /* nn_message_identity_t message_identity         */
 | 
			
		||||
  XG, Xl,              /* nn_message_identity_t related_message_identity */
 | 
			
		||||
  XG,                  /* ddsi_guid_t destinaton_participant_guid        */
 | 
			
		||||
  XG,                  /* ddsi_guid_t destination_endpoint_guid          */
 | 
			
		||||
  XG,                  /* ddsi_guid_t source_endpoint_guid               */
 | 
			
		||||
  XS,                  /* char* message_class_id                         */
 | 
			
		||||
  XQ,                  /* nn_dataholderseq_t message_data                */
 | 
			
		||||
    /* nn_dataholder_t */
 | 
			
		||||
    XS,                  /* char* class_id                               */
 | 
			
		||||
    XQ,                  /* dds_propertyseq_t properties                 */
 | 
			
		||||
      XbPROP, XS, XS,      /* dds_property_t                             */
 | 
			
		||||
    XSTOP,
 | 
			
		||||
    XQ,                  /* dds_binarypropertyseq_t binary_properties    */
 | 
			
		||||
      XbPROP, XS, XO,      /* dds_binaryproperty_t                       */
 | 
			
		||||
    XSTOP,
 | 
			
		||||
  XSTOP,
 | 
			
		||||
  XSTOP                /* end                                            */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
alias_simple_sequence(ddsi_octetseq_t *dst, const ddsi_octetseq_t *src, size_t elem_size)
 | 
			
		||||
{
 | 
			
		||||
  dst->length = src->length;
 | 
			
		||||
  if (src->length > 0)
 | 
			
		||||
  {
 | 
			
		||||
    /* Even when aliased, sequence buffers are not shared. */
 | 
			
		||||
    dst->value = ddsrt_memdup(src->value, src->length * elem_size);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
alias_dataholder(nn_dataholder_t *dst, const nn_dataholder_t *src)
 | 
			
		||||
{
 | 
			
		||||
  dst->class_id = src->class_id;
 | 
			
		||||
  alias_simple_sequence((ddsi_octetseq_t*)&dst->properties,
 | 
			
		||||
                        (const ddsi_octetseq_t*)&src->properties,
 | 
			
		||||
                        sizeof(dds_property_t));
 | 
			
		||||
  alias_simple_sequence((ddsi_octetseq_t*)&dst->binary_properties,
 | 
			
		||||
                        (const ddsi_octetseq_t*)&src->binary_properties,
 | 
			
		||||
                        sizeof(dds_binaryproperty_t));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
alias_dataholderseq(nn_dataholderseq_t *dst, const nn_dataholderseq_t *src)
 | 
			
		||||
{
 | 
			
		||||
  dst->n = src->n;
 | 
			
		||||
  if (src->n > 0)
 | 
			
		||||
  {
 | 
			
		||||
    /* Even when aliased, sequence buffers are not shared. */
 | 
			
		||||
    dst->tags = ddsrt_malloc(src->n * sizeof(nn_dataholder_t));
 | 
			
		||||
    for (uint32_t i = 0; i < src->n; i++)
 | 
			
		||||
    {
 | 
			
		||||
      alias_dataholder(&(dst->tags[i]), &(src->tags[i]));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
nn_participant_generic_message_init(
 | 
			
		||||
   nn_participant_generic_message_t *msg,
 | 
			
		||||
   const ddsi_guid_t *wrguid,
 | 
			
		||||
   int64_t wrseq,
 | 
			
		||||
   const ddsi_guid_t *dstpguid,
 | 
			
		||||
   const ddsi_guid_t *dsteguid,
 | 
			
		||||
   const ddsi_guid_t *srceguid,
 | 
			
		||||
   const char *classid,
 | 
			
		||||
   const nn_dataholderseq_t *mdata,
 | 
			
		||||
   const nn_message_identity_t *rmid)
 | 
			
		||||
{
 | 
			
		||||
  assert(msg);
 | 
			
		||||
  assert(wrguid);
 | 
			
		||||
  assert(classid);
 | 
			
		||||
 | 
			
		||||
  memset(msg, 0, sizeof(*msg));
 | 
			
		||||
 | 
			
		||||
  msg->message_identity.source_guid = *wrguid;
 | 
			
		||||
  msg->message_identity.sequence_number = wrseq;
 | 
			
		||||
 | 
			
		||||
  if (rmid)
 | 
			
		||||
  {
 | 
			
		||||
    msg->related_message_identity.source_guid = rmid->source_guid;
 | 
			
		||||
    msg->related_message_identity.sequence_number = rmid->sequence_number;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (dstpguid)
 | 
			
		||||
    msg->destinaton_participant_guid = *dstpguid;
 | 
			
		||||
 | 
			
		||||
  if (dsteguid)
 | 
			
		||||
    msg->destination_endpoint_guid = *dsteguid;
 | 
			
		||||
 | 
			
		||||
  if (srceguid)
 | 
			
		||||
    msg->source_endpoint_guid = *srceguid;
 | 
			
		||||
 | 
			
		||||
  msg->message_class_id = classid;
 | 
			
		||||
 | 
			
		||||
  if (mdata)
 | 
			
		||||
    alias_dataholderseq(&msg->message_data, mdata);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
nn_participant_generic_message_deinit(
 | 
			
		||||
   nn_participant_generic_message_t *msg)
 | 
			
		||||
{
 | 
			
		||||
  assert(msg);
 | 
			
		||||
  plist_fini_generic(msg, pserop_participant_generic_message, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
nn_participant_generic_message_serialize(
 | 
			
		||||
   const nn_participant_generic_message_t *msg,
 | 
			
		||||
   unsigned char **data,
 | 
			
		||||
   size_t *len)
 | 
			
		||||
{
 | 
			
		||||
  return plist_ser_generic ((void**)data, len, (void*)msg, pserop_participant_generic_message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
nn_participant_generic_message_deseralize(
 | 
			
		||||
   nn_participant_generic_message_t *msg,
 | 
			
		||||
   const unsigned char *data,
 | 
			
		||||
   size_t len,
 | 
			
		||||
   bool bswap)
 | 
			
		||||
{
 | 
			
		||||
  assert(sizeof(nn_participant_generic_message_t) == plist_memsize_generic(pserop_participant_generic_message));
 | 
			
		||||
  return plist_deser_generic (msg, data, len, bswap, pserop_participant_generic_message);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -114,8 +114,6 @@ struct piddesc {
 | 
			
		|||
  dds_return_t (*deser_validate_xform) (void * __restrict dst, const struct dd * __restrict dd);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern inline bool pserop_seralign_is_1 (enum pserop op);
 | 
			
		||||
 | 
			
		||||
static void log_octetseq (uint32_t cat, const struct ddsrt_log_cfg *logcfg, uint32_t n, const unsigned char *xs);
 | 
			
		||||
static dds_return_t validate_history_qospolicy (const dds_history_qospolicy_t *q);
 | 
			
		||||
static dds_return_t validate_resource_limits_qospolicy (const dds_resource_limits_qospolicy_t *q);
 | 
			
		||||
| 
						 | 
				
			
			@ -127,26 +125,70 @@ static dds_return_t final_validation_qos (const dds_qos_t *dest, nn_protocol_ver
 | 
			
		|||
static int partitions_equal (const dds_partition_qospolicy_t *a, const dds_partition_qospolicy_t *b);
 | 
			
		||||
static dds_return_t nn_xqos_valid_strictness (const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos, bool strict);
 | 
			
		||||
 | 
			
		||||
static size_t align4size (size_t x)
 | 
			
		||||
static size_t pserop_seralign(enum pserop op)
 | 
			
		||||
{
 | 
			
		||||
  return (x + 3) & ~(size_t)3;
 | 
			
		||||
  switch(op)
 | 
			
		||||
  {
 | 
			
		||||
    case XSTOP:
 | 
			
		||||
    case XbPROP:
 | 
			
		||||
    case Xopt:
 | 
			
		||||
      /* NB: XbPROP is never serialized, so its alignment is irrelevant.  If ever there
 | 
			
		||||
         is a need to allow calling this function when op = XbPROP, it needs to be changed
 | 
			
		||||
         to taking the address of the pserop, and in that case inspect the following
 | 
			
		||||
         operator */
 | 
			
		||||
      assert(false);
 | 
			
		||||
      return 1;
 | 
			
		||||
    case Xo: case Xox2:
 | 
			
		||||
    case Xb: case Xbx2:
 | 
			
		||||
    case XbCOND:
 | 
			
		||||
    case XG:
 | 
			
		||||
    case XK:
 | 
			
		||||
      return 1;
 | 
			
		||||
    case XO:
 | 
			
		||||
    case XS:
 | 
			
		||||
    case XE1: case XE2: case XE3:
 | 
			
		||||
    case Xi: case Xix2: case Xix3: case Xix4:
 | 
			
		||||
    case Xu: case Xux2: case Xux3: case Xux4: case Xux5:
 | 
			
		||||
    case XD: case XDx2:
 | 
			
		||||
    case XQ:
 | 
			
		||||
      return 4;
 | 
			
		||||
    case Xl:
 | 
			
		||||
      return 8;
 | 
			
		||||
  }
 | 
			
		||||
  assert(false);
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *deser_generic_dst (void * __restrict dst, size_t *dstoff, size_t align)
 | 
			
		||||
static size_t alignN(const size_t off, const size_t align)
 | 
			
		||||
{
 | 
			
		||||
  *dstoff = (*dstoff + align - 1) & ~(align - 1);
 | 
			
		||||
  return (off + align - 1) & ~(align - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t align4(const size_t off)
 | 
			
		||||
{
 | 
			
		||||
  return alignN(off, 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t align8(const size_t off)
 | 
			
		||||
{
 | 
			
		||||
  return alignN(off, 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *deser_generic_dst (void * __restrict dst, size_t *dstoff, const size_t align)
 | 
			
		||||
{
 | 
			
		||||
  *dstoff = alignN(*dstoff, align);
 | 
			
		||||
  return (char *) dst + *dstoff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const void *deser_generic_src (const void * __restrict src, size_t *srcoff, size_t align)
 | 
			
		||||
static const void *deser_generic_src (const void * __restrict src, size_t *srcoff, const size_t align)
 | 
			
		||||
{
 | 
			
		||||
  *srcoff = (*srcoff + align - 1) & ~(align - 1);
 | 
			
		||||
  *srcoff = alignN(*srcoff, align);
 | 
			
		||||
  return (const char *) src + *srcoff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *ser_generic_align4 (char * __restrict p, size_t * __restrict off)
 | 
			
		||||
static void *ser_generic_aligned (char * __restrict p, size_t * __restrict off, const size_t align)
 | 
			
		||||
{
 | 
			
		||||
  const size_t off1 = align4size (*off);
 | 
			
		||||
  const size_t off1 = alignN(*off, align);
 | 
			
		||||
  size_t pad = off1 - *off;
 | 
			
		||||
  char *dst = p + *off;
 | 
			
		||||
  *off = off1;
 | 
			
		||||
| 
						 | 
				
			
			@ -155,6 +197,16 @@ static void *ser_generic_align4 (char * __restrict p, size_t * __restrict off)
 | 
			
		|||
  return dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *ser_generic_align4(char * __restrict p, size_t * __restrict off)
 | 
			
		||||
{
 | 
			
		||||
  return ser_generic_aligned(p, off, 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *ser_generic_align8(char * __restrict p, size_t * __restrict off)
 | 
			
		||||
{
 | 
			
		||||
  return ser_generic_aligned(p, off, 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t deser_uint32 (uint32_t *dst, const struct dd * __restrict dd, size_t * __restrict off)
 | 
			
		||||
{
 | 
			
		||||
  size_t off1 = (*off + 3) & ~(size_t)3;
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +221,20 @@ static dds_return_t deser_uint32 (uint32_t *dst, const struct dd * __restrict dd
 | 
			
		|||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t deser_int64 (int64_t *dst, const struct dd * __restrict dd, size_t * __restrict off)
 | 
			
		||||
{
 | 
			
		||||
  size_t off1 = (*off + 7) & ~(size_t)7;
 | 
			
		||||
  int64_t tmp;
 | 
			
		||||
  if (off1 + 8 > dd->bufsz)
 | 
			
		||||
    return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
  tmp = *((int64_t *) (dd->buf + off1));
 | 
			
		||||
  if (dd->bswap)
 | 
			
		||||
    tmp = bswap8 (tmp);
 | 
			
		||||
  *dst = tmp;
 | 
			
		||||
  *off = off1 + 8;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define alignof(type_) offsetof (struct { char c; type_ d; }, d)
 | 
			
		||||
 | 
			
		||||
static dds_return_t deser_reliability (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff)
 | 
			
		||||
| 
						 | 
				
			
			@ -310,6 +376,28 @@ static dds_return_t fini_locator (void * __restrict dst, size_t * __restrict dst
 | 
			
		|||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const enum pserop* pserop_advance (const enum pserop * __restrict desc)
 | 
			
		||||
{
 | 
			
		||||
  /* Should not start on an end. */
 | 
			
		||||
  assert(*desc != XSTOP);
 | 
			
		||||
 | 
			
		||||
  /* If not a sequence, return next. */
 | 
			
		||||
  if (*desc != XQ) return (desc + 1);
 | 
			
		||||
 | 
			
		||||
  /* Jump over this sequence (ignoring nested ones). */
 | 
			
		||||
  int scope = 1;
 | 
			
		||||
  do
 | 
			
		||||
  {
 | 
			
		||||
    desc++;
 | 
			
		||||
    if (*desc ==    XQ) scope++;
 | 
			
		||||
    if (*desc == XSTOP) scope--;
 | 
			
		||||
  }
 | 
			
		||||
  while (scope != 0);
 | 
			
		||||
 | 
			
		||||
  /* We're on the stop, return next. */
 | 
			
		||||
  return (desc + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t ser_generic_srcsize (const enum pserop * __restrict desc)
 | 
			
		||||
{
 | 
			
		||||
  size_t srcoff = 0, srcalign = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -330,6 +418,7 @@ static size_t ser_generic_srcsize (const enum pserop * __restrict desc)
 | 
			
		|||
      case XE1: case XE2: case XE3: SIMPLE (*desc, unsigned); break;
 | 
			
		||||
      case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break;
 | 
			
		||||
      case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break;
 | 
			
		||||
      case Xl: SIMPLE (Xl, int64_t); break;
 | 
			
		||||
      case XD: case XDx2: SIMPLE (XD, dds_duration_t); break;
 | 
			
		||||
      case Xo: case Xox2: SIMPLE (Xo, unsigned char); break;
 | 
			
		||||
      case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -337,10 +426,10 @@ static size_t ser_generic_srcsize (const enum pserop * __restrict desc)
 | 
			
		|||
      case XG: SIMPLE (XG, ddsi_guid_t); break;
 | 
			
		||||
      case XK: SIMPLE (XK, nn_keyhash_t); break;
 | 
			
		||||
      case XbPROP: SIMPLE (XbPROP, unsigned char); break;
 | 
			
		||||
      case XQ: SIMPLE (XQ, ddsi_octetseq_t); while (*++desc != XSTOP) { } break;
 | 
			
		||||
      case XQ: SIMPLE (XQ, ddsi_octetseq_t); break;
 | 
			
		||||
      case Xopt: break;
 | 
			
		||||
    }
 | 
			
		||||
    desc++;
 | 
			
		||||
    desc = pserop_advance(desc);
 | 
			
		||||
  }
 | 
			
		||||
#undef SIMPLE
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -350,8 +439,9 @@ size_t plist_memsize_generic (const enum pserop * __restrict desc)
 | 
			
		|||
  return ser_generic_srcsize (desc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fini_generic_embeddable (void * __restrict dst, size_t * __restrict dstoff, const enum pserop *desc, const enum pserop * const desc_end, bool aliased)
 | 
			
		||||
static bool fini_generic_embeddable (void * __restrict dst, size_t * __restrict dstoff, const enum pserop *desc, const enum pserop * const desc_end, bool aliased)
 | 
			
		||||
{
 | 
			
		||||
  bool freed = false;
 | 
			
		||||
#define COMPLEX(basecase_, type_, cleanup_unaliased_, cleanup_always_) do { \
 | 
			
		||||
    type_ *x = deser_generic_dst (dst, dstoff, alignof (type_));            \
 | 
			
		||||
    const uint32_t cnt = 1 + (uint32_t) (*desc - (basecase_));              \
 | 
			
		||||
| 
						 | 
				
			
			@ -362,16 +452,17 @@ static void fini_generic_embeddable (void * __restrict dst, size_t * __restrict
 | 
			
		|||
    *dstoff += cnt * sizeof (*x);                                           \
 | 
			
		||||
  } while (0)
 | 
			
		||||
#define SIMPLE(basecase_, type_) COMPLEX (basecase_, type_, (void) 0, (void) 0)
 | 
			
		||||
  while (desc != desc_end)
 | 
			
		||||
  while ((desc_end == NULL) || (desc < desc_end))
 | 
			
		||||
  {
 | 
			
		||||
    switch (*desc)
 | 
			
		||||
    {
 | 
			
		||||
      case XSTOP: return;
 | 
			
		||||
      case XO: COMPLEX (XO, ddsi_octetseq_t, ddsrt_free (x->value), (void) 0); break;
 | 
			
		||||
      case XS: COMPLEX (XS, char *, ddsrt_free (*x), (void) 0); break;
 | 
			
		||||
      case XSTOP: return freed;
 | 
			
		||||
      case XO: COMPLEX (XO, ddsi_octetseq_t, { ddsrt_free (x->value); freed = true; }, (void) 0); break;
 | 
			
		||||
      case XS: COMPLEX (XS, char *, { ddsrt_free (*x); freed = true; }, (void) 0); break;
 | 
			
		||||
      case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, (void) 0, (void) 0); break;
 | 
			
		||||
      case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break;
 | 
			
		||||
      case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break;
 | 
			
		||||
      case Xl: SIMPLE (Xl, int64_t); break;
 | 
			
		||||
      case XD: case XDx2: SIMPLE (XD, dds_duration_t); break;
 | 
			
		||||
      case Xo: case Xox2: SIMPLE (Xo, unsigned char); break;
 | 
			
		||||
      case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -380,23 +471,27 @@ static void fini_generic_embeddable (void * __restrict dst, size_t * __restrict
 | 
			
		|||
      case XK: SIMPLE (XK, nn_keyhash_t); break;
 | 
			
		||||
      case XbPROP: SIMPLE (XbPROP, unsigned char); break;
 | 
			
		||||
      case XQ:
 | 
			
		||||
        /* 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);
 | 
			
		||||
          for (uint32_t i = 0; i < x->length; i++) {
 | 
			
		||||
            size_t elem_off = i * elem_size;
 | 
			
		||||
            fini_generic_embeddable (x->value, &elem_off, desc + 1, desc_end, aliased);
 | 
			
		||||
          }
 | 
			
		||||
        }, ddsrt_free (x->value));
 | 
			
		||||
        while (desc + 1 != desc_end && *++desc != XSTOP) { }
 | 
			
		||||
        break;
 | 
			
		||||
      {
 | 
			
		||||
        ddsi_octetseq_t *x = deser_generic_dst (dst, dstoff, alignof (ddsi_octetseq_t));
 | 
			
		||||
        const size_t elem_size = ser_generic_srcsize (desc + 1);
 | 
			
		||||
        bool elem_freed = true;
 | 
			
		||||
        for (uint32_t i = 0; (i < x->length) && elem_freed; i++)
 | 
			
		||||
        {
 | 
			
		||||
          size_t elem_off = i * elem_size;
 | 
			
		||||
          elem_freed = fini_generic_embeddable (x->value, &elem_off, desc + 1, desc_end, aliased);
 | 
			
		||||
        }
 | 
			
		||||
        ddsrt_free (x->value);
 | 
			
		||||
        freed = true;
 | 
			
		||||
        *dstoff += sizeof (ddsi_octetseq_t);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
      case Xopt: break;
 | 
			
		||||
    }
 | 
			
		||||
    desc++;
 | 
			
		||||
    desc = pserop_advance(desc);
 | 
			
		||||
  }
 | 
			
		||||
#undef SIMPLE
 | 
			
		||||
#undef COMPLEX
 | 
			
		||||
  return freed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t pserop_memalign (enum pserop op)
 | 
			
		||||
| 
						 | 
				
			
			@ -413,13 +508,14 @@ static size_t pserop_memalign (enum pserop op)
 | 
			
		|||
    case XE1: case XE2: case XE3: return sizeof (uint32_t);
 | 
			
		||||
    case Xi: case Xix2: case Xix3: case Xix4: return sizeof (int32_t);
 | 
			
		||||
    case Xu: case Xux2: case Xux3: case Xux4: case Xux5: return sizeof (uint32_t);
 | 
			
		||||
    case Xl: return alignof (int64_t);
 | 
			
		||||
    case XD: case XDx2: return alignof (dds_duration_t);
 | 
			
		||||
    case XSTOP: case Xopt: assert (0);
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff, const enum pserop * __restrict desc)
 | 
			
		||||
static dds_return_t deser_generic_r (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff, const enum pserop * __restrict desc)
 | 
			
		||||
{
 | 
			
		||||
  enum pserop const * const desc_in = desc;
 | 
			
		||||
  size_t dstoff_in = *dstoff;
 | 
			
		||||
| 
						 | 
				
			
			@ -448,7 +544,7 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
 | 
			
		|||
        char ** const x = deser_generic_dst (dst, dstoff, alignof (char *));
 | 
			
		||||
        ddsi_octetseq_t tmp;
 | 
			
		||||
        size_t tmpoff = 0;
 | 
			
		||||
        if (deser_generic (&tmp, &tmpoff, flagset, flag, dd, srcoff, (enum pserop []) { XO, XSTOP }) < 0)
 | 
			
		||||
        if (deser_generic_r (&tmp, &tmpoff, flagset, flag, dd, srcoff, (enum pserop []) { XO, XSTOP }) < 0)
 | 
			
		||||
          goto fail;
 | 
			
		||||
        if (tmp.length < 1 || tmp.value[tmp.length - 1] != 0)
 | 
			
		||||
          goto fail;
 | 
			
		||||
| 
						 | 
				
			
			@ -484,6 +580,13 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
 | 
			
		|||
        *dstoff += cnt * sizeof (*x);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case Xl: { /* int64_t */
 | 
			
		||||
        int64_t * const x = deser_generic_dst (dst, dstoff, alignof (int64_t));
 | 
			
		||||
        if (deser_int64(x, dd, srcoff) < 0)
 | 
			
		||||
          goto fail;
 | 
			
		||||
        *dstoff += sizeof (*x);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */
 | 
			
		||||
        dds_duration_t * const x = deser_generic_dst (dst, dstoff, alignof (dds_duration_t));
 | 
			
		||||
        const uint32_t cnt = 1 + (uint32_t) (*desc - XD);
 | 
			
		||||
| 
						 | 
				
			
			@ -547,7 +650,7 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
 | 
			
		|||
        *dstoff += sizeof (*x);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case XQ: { /* non-nested but otherwise arbitrary sequence, so no nested mallocs */
 | 
			
		||||
      case XQ: { /* arbitrary sequence */
 | 
			
		||||
        ddsi_octetseq_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_octetseq_t));
 | 
			
		||||
        if (deser_uint32 (&x->length, dd, srcoff) < 0 || x->length > dd->bufsz - *srcoff)
 | 
			
		||||
          goto fail;
 | 
			
		||||
| 
						 | 
				
			
			@ -556,25 +659,26 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
 | 
			
		|||
        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)
 | 
			
		||||
          if (deser_generic_r (x->value, &elem_off, flagset, flag, dd, srcoff, desc + 1) < 0)
 | 
			
		||||
          {
 | 
			
		||||
            bool elem_freed = true;
 | 
			
		||||
            for (uint32_t f = 0; (f < i) && (elem_freed); f++)
 | 
			
		||||
            {
 | 
			
		||||
              size_t free_off = f * elem_size;
 | 
			
		||||
              elem_freed = fini_generic_embeddable (x->value, &free_off, desc + 1, NULL, *flagset->aliased & flag);
 | 
			
		||||
            }
 | 
			
		||||
            ddsrt_free (x->value);
 | 
			
		||||
            goto fail;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        *dstoff += sizeof (*x);
 | 
			
		||||
        while (*++desc != XSTOP) { }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case Xopt: { /* remainder is optional; alignment is very nearly always 4 */
 | 
			
		||||
        bool end_of_input;
 | 
			
		||||
        if (pserop_seralign_is_1 (desc[1]))
 | 
			
		||||
          end_of_input = (*srcoff + 1 > dd->bufsz);
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
          *srcoff = (*srcoff + 3) & ~(size_t)3;
 | 
			
		||||
          end_of_input = (*srcoff + 4 > dd->bufsz);
 | 
			
		||||
        }
 | 
			
		||||
        size_t align = pserop_seralign(desc[1]);
 | 
			
		||||
        *srcoff = alignN(*srcoff, align);
 | 
			
		||||
        end_of_input = (*srcoff + align > dd->bufsz);
 | 
			
		||||
        if (end_of_input)
 | 
			
		||||
        {
 | 
			
		||||
          void * const x = deser_generic_dst (dst, dstoff, pserop_memalign (desc[1]));
 | 
			
		||||
| 
						 | 
				
			
			@ -584,19 +688,29 @@ static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict ds
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    desc++;
 | 
			
		||||
    desc = pserop_advance(desc);
 | 
			
		||||
  }
 | 
			
		||||
success:
 | 
			
		||||
  *flagset->present |= flag;
 | 
			
		||||
  return 0;
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
  fini_generic_embeddable (dst, &dstoff_in, desc_in, desc, *flagset->aliased & flag);
 | 
			
		||||
  *flagset->present &= ~flag;
 | 
			
		||||
  *flagset->aliased &= ~flag;
 | 
			
		||||
  (void)fini_generic_embeddable (dst, &dstoff_in, desc_in, desc, *flagset->aliased & flag);
 | 
			
		||||
  return DDS_RETCODE_BAD_PARAMETER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t deser_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff, const enum pserop * __restrict desc)
 | 
			
		||||
{
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  ret = deser_generic_r (dst, dstoff, flagset, flag, dd, srcoff, desc);
 | 
			
		||||
  if (ret != 0)
 | 
			
		||||
  {
 | 
			
		||||
    *flagset->present &= ~flag;
 | 
			
		||||
    *flagset->aliased &= ~flag;
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t plist_deser_generic (void * __restrict dst, const void * __restrict src, size_t srcsize, bool bswap, const enum pserop * __restrict desc)
 | 
			
		||||
{
 | 
			
		||||
  struct dd dd = {
 | 
			
		||||
| 
						 | 
				
			
			@ -622,17 +736,19 @@ static void ser_generic_size_embeddable (size_t *dstoff, const void *src, size_t
 | 
			
		|||
    srcoff += cnt * sizeof (*x);                                        \
 | 
			
		||||
  } while (0)
 | 
			
		||||
#define SIMPLE1(basecase_, type_) COMPLEX (basecase_, type_, *dstoff = *dstoff + sizeof (*x))
 | 
			
		||||
#define SIMPLE4(basecase_, type_) COMPLEX (basecase_, type_, *dstoff = align4size (*dstoff) + sizeof (*x))
 | 
			
		||||
#define SIMPLE4(basecase_, type_) COMPLEX (basecase_, type_, *dstoff = align4 (*dstoff) + sizeof (*x))
 | 
			
		||||
#define SIMPLE8(basecase_, type_) COMPLEX (basecase_, type_, *dstoff = align8 (*dstoff) + sizeof (*x))
 | 
			
		||||
  while (true)
 | 
			
		||||
  {
 | 
			
		||||
    switch (*desc)
 | 
			
		||||
    {
 | 
			
		||||
      case XSTOP: return;
 | 
			
		||||
      case XO: COMPLEX (XO, ddsi_octetseq_t, *dstoff = align4size (*dstoff) + 4 + x->length); break;
 | 
			
		||||
      case XS: COMPLEX (XS, const char *, *dstoff = align4size (*dstoff) + 4 + strlen (*x) + 1); break;
 | 
			
		||||
      case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, *dstoff = align4size (*dstoff) + 4); break;
 | 
			
		||||
      case XO: COMPLEX (XO, ddsi_octetseq_t, *dstoff = align4 (*dstoff) + 4 + x->length); break;
 | 
			
		||||
      case XS: COMPLEX (XS, const char *, *dstoff = align4 (*dstoff) + 4 + strlen (*x) + 1); break;
 | 
			
		||||
      case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, *dstoff = align4 (*dstoff) + 4); break;
 | 
			
		||||
      case Xi: case Xix2: case Xix3: case Xix4: SIMPLE4 (Xi, int32_t); break;
 | 
			
		||||
      case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE4 (Xu, uint32_t); break;
 | 
			
		||||
      case Xl: SIMPLE8 (Xl, int64_t); break;
 | 
			
		||||
      case XD: case XDx2: SIMPLE4 (XD, dds_duration_t); break;
 | 
			
		||||
      case Xo: case Xox2: SIMPLE1 (Xo, unsigned char); break;
 | 
			
		||||
      case Xb: case Xbx2: SIMPLE1 (Xb, unsigned char); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -643,14 +759,15 @@ static void ser_generic_size_embeddable (size_t *dstoff, const void *src, size_t
 | 
			
		|||
               COMPLEX (XbPROP, unsigned char, if (! *x) return); break;
 | 
			
		||||
      case XQ: COMPLEX (XQ, ddsi_octetseq_t, {
 | 
			
		||||
        const size_t elem_size = ser_generic_srcsize (desc + 1);
 | 
			
		||||
        *dstoff = align4size (*dstoff) + 4;
 | 
			
		||||
        *dstoff = align4 (*dstoff) + 4;
 | 
			
		||||
        for (uint32_t i = 0; i < x->length; i++)
 | 
			
		||||
          ser_generic_size_embeddable (dstoff, x->value, i * elem_size, desc + 1);
 | 
			
		||||
      }); while (*++desc != XSTOP) { } break;
 | 
			
		||||
      }); break;
 | 
			
		||||
      case Xopt: break;
 | 
			
		||||
    }
 | 
			
		||||
    desc++;
 | 
			
		||||
    desc = pserop_advance(desc);
 | 
			
		||||
  }
 | 
			
		||||
#undef SIMPLE8
 | 
			
		||||
#undef SIMPLE4
 | 
			
		||||
#undef SIMPLE1
 | 
			
		||||
#undef COMPLEX
 | 
			
		||||
| 
						 | 
				
			
			@ -733,6 +850,14 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c
 | 
			
		|||
        srcoff += cnt * sizeof (*x);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case Xl: { /* int64_t */
 | 
			
		||||
        int64_t const * const x = deser_generic_src (src, &srcoff, alignof (int64_t));
 | 
			
		||||
        int64_t * const p = ser_generic_align8 (data, dstoff);
 | 
			
		||||
        *p = *x;
 | 
			
		||||
        *dstoff += sizeof (*x);
 | 
			
		||||
        srcoff += sizeof (*x);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case XD: case XDx2: { /* duration(s): int64_t <=> int32_t.uint32_t (seconds.fraction) */
 | 
			
		||||
        dds_duration_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_duration_t));
 | 
			
		||||
        const uint32_t cnt = 1 + (uint32_t) (*desc - XD);
 | 
			
		||||
| 
						 | 
				
			
			@ -788,7 +913,7 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c
 | 
			
		|||
        srcoff += sizeof (*x);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case XQ: {
 | 
			
		||||
      case XQ: { /* arbitrary sequence */
 | 
			
		||||
        ddsi_octetseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_octetseq_t));
 | 
			
		||||
        char * const p = ser_generic_align4 (data, dstoff);
 | 
			
		||||
        *dstoff += 4;
 | 
			
		||||
| 
						 | 
				
			
			@ -802,13 +927,12 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c
 | 
			
		|||
            ser_generic_embeddable (data, dstoff, x->value, i * elem_size, desc + 1);
 | 
			
		||||
        }
 | 
			
		||||
        srcoff += sizeof (*x);
 | 
			
		||||
        while (*++desc != XSTOP) { }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case Xopt:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    desc++;
 | 
			
		||||
    desc = pserop_advance(desc);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -852,6 +976,7 @@ static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict
 | 
			
		|||
      case XE1: case XE2: case XE3: COMPLEX (*desc, unsigned, (void) 0); break;
 | 
			
		||||
      case Xi: case Xix2: case Xix3: case Xix4: SIMPLE (Xi, int32_t); break;
 | 
			
		||||
      case Xu: case Xux2: case Xux3: case Xux4: case Xux5: SIMPLE (Xu, uint32_t); break;
 | 
			
		||||
      case Xl: SIMPLE(Xl, int64_t); break;
 | 
			
		||||
      case XD: case XDx2: SIMPLE (XD, dds_duration_t); break;
 | 
			
		||||
      case Xo: case Xox2: SIMPLE (Xo, unsigned char); break;
 | 
			
		||||
      case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -877,10 +1002,10 @@ static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict
 | 
			
		|||
          size_t elem_off = i * elem_size;
 | 
			
		||||
          unalias_generic (x->value, &elem_off, gen_seq_aliased, desc + 1);
 | 
			
		||||
        }
 | 
			
		||||
      }); while (*++desc != XSTOP) { } break;
 | 
			
		||||
      }); break;
 | 
			
		||||
      case Xopt: break;
 | 
			
		||||
    }
 | 
			
		||||
    desc++;
 | 
			
		||||
    desc = pserop_advance(desc);
 | 
			
		||||
  }
 | 
			
		||||
#undef SIMPLE
 | 
			
		||||
#undef COMPLEX
 | 
			
		||||
| 
						 | 
				
			
			@ -915,14 +1040,14 @@ static bool fini_generic_required (const enum pserop * __restrict desc)
 | 
			
		|||
 | 
			
		||||
static dds_return_t fini_generic (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const enum pserop * __restrict desc)
 | 
			
		||||
{
 | 
			
		||||
  fini_generic_embeddable (dst, dstoff, desc, NULL, *flagset->aliased & flag);
 | 
			
		||||
  (void)fini_generic_embeddable (dst, dstoff, desc, NULL, *flagset->aliased & flag);
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void plist_fini_generic (void * __restrict dst, const enum pserop *desc, bool aliased)
 | 
			
		||||
{
 | 
			
		||||
  size_t dstoff = 0;
 | 
			
		||||
  fini_generic_embeddable (dst, &dstoff, desc, NULL, aliased);
 | 
			
		||||
  (void)fini_generic_embeddable (dst, &dstoff, desc, NULL, aliased);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static dds_return_t valid_generic (const void *src, size_t srcoff, const enum pserop * __restrict desc)
 | 
			
		||||
| 
						 | 
				
			
			@ -945,6 +1070,7 @@ static dds_return_t valid_generic (const void *src, size_t srcoff, const enum ps
 | 
			
		|||
      case XE1: case XE2: case XE3: SIMPLE (*desc, unsigned, *x <= 1 + (unsigned) *desc - XE1); break;
 | 
			
		||||
      case Xi: case Xix2: case Xix3: case Xix4: TRIVIAL (Xi, int32_t); break;
 | 
			
		||||
      case Xu: case Xux2: case Xux3: case Xux4: case Xux5: TRIVIAL (Xu, uint32_t); break;
 | 
			
		||||
      case Xl: TRIVIAL(Xl, int64_t); break;
 | 
			
		||||
      case XD: case XDx2: SIMPLE (XD, dds_duration_t, *x >= 0); break;
 | 
			
		||||
      case Xo: case Xox2: TRIVIAL (Xo, unsigned char); break;
 | 
			
		||||
      case Xb: case Xbx2: SIMPLE (Xb, unsigned char, *x == 0 || *x == 1); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -963,10 +1089,10 @@ static dds_return_t valid_generic (const void *src, size_t srcoff, const enum ps
 | 
			
		|||
              return ret;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }); while (*++desc != XSTOP) { } break;
 | 
			
		||||
      }); break;
 | 
			
		||||
      case Xopt: break;
 | 
			
		||||
    }
 | 
			
		||||
    desc++;
 | 
			
		||||
    desc = pserop_advance(desc);
 | 
			
		||||
  }
 | 
			
		||||
#undef TRIVIAL
 | 
			
		||||
#undef SIMPLE
 | 
			
		||||
| 
						 | 
				
			
			@ -1001,6 +1127,7 @@ static bool equal_generic (const void *srcx, const void *srcy, size_t srcoff, co
 | 
			
		|||
      case XE1: case XE2: case XE3: TRIVIAL (*desc, unsigned); break;
 | 
			
		||||
      case Xi: case Xix2: case Xix3: case Xix4: TRIVIAL (Xi, int32_t); break;
 | 
			
		||||
      case Xu: case Xux2: case Xux3: case Xux4: case Xux5: TRIVIAL (Xu, uint32_t); break;
 | 
			
		||||
      case Xl: TRIVIAL (Xl, int64_t); break;
 | 
			
		||||
      case XD: case XDx2: TRIVIAL (XD, dds_duration_t); break;
 | 
			
		||||
      case Xo: case Xox2: TRIVIAL (Xo, unsigned char); break;
 | 
			
		||||
      case Xb: case Xbx2: TRIVIAL (Xb, unsigned char); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1025,10 +1152,10 @@ static bool equal_generic (const void *srcx, const void *srcy, size_t srcoff, co
 | 
			
		|||
              return false;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }); while (*++desc != XSTOP) { } break;
 | 
			
		||||
      }); break;
 | 
			
		||||
      case Xopt: break;
 | 
			
		||||
    }
 | 
			
		||||
    desc++;
 | 
			
		||||
    desc = pserop_advance(desc);
 | 
			
		||||
  }
 | 
			
		||||
#undef TRIVIAL
 | 
			
		||||
#undef SIMPLE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,12 @@ include(CUnit)
 | 
			
		|||
 | 
			
		||||
set(ddsi_test_sources
 | 
			
		||||
    "plist_generic.c"
 | 
			
		||||
    "plist.c")
 | 
			
		||||
    "plist.c"
 | 
			
		||||
    "mem_ser.h")
 | 
			
		||||
 | 
			
		||||
if(ENABLE_SECURITY)
 | 
			
		||||
  set(ddsi_test_sources ${ddsi_test_sources} "security_msg.c")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
add_cunit_executable(cunit_ddsi ${ddsi_test_sources})
 | 
			
		||||
target_include_directories(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										55
									
								
								src/core/ddsi/tests/mem_ser.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/core/ddsi/tests/mem_ser.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright(c) 2019 ADLINK Technology Limited and others
 | 
			
		||||
 *
 | 
			
		||||
 * This program and the accompanying materials are made available under the
 | 
			
		||||
 * terms of the Eclipse Public License v. 2.0 which is available at
 | 
			
		||||
 * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
 | 
			
		||||
 * v. 1.0 which is available at
 | 
			
		||||
 * http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 | 
			
		||||
 */
 | 
			
		||||
#ifndef DDSI_TEST_MEM_SER_H
 | 
			
		||||
#define DDSI_TEST_MEM_SER_H
 | 
			
		||||
 | 
			
		||||
#include "dds/ddsrt/endian.h"
 | 
			
		||||
 | 
			
		||||
#if DDSRT_ENDIAN == DDSRT_BIG_ENDIAN
 | 
			
		||||
#define SER32(v) \
 | 
			
		||||
  (unsigned char)( (uint32_t)(v) >> 24        ), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 16) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >>  8) & 0xff), \
 | 
			
		||||
  (unsigned char)( (uint32_t)(v)        & 0xff)
 | 
			
		||||
#define SER32BE(v) SER32(v)
 | 
			
		||||
#define SER64(v) \
 | 
			
		||||
  (unsigned char)( (uint32_t)(v) >> 56),         \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 48) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 40) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 32) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 24) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 16) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >>  8) & 0xff), \
 | 
			
		||||
  (unsigned char)( (uint32_t)(v)        & 0xff)
 | 
			
		||||
#else
 | 
			
		||||
#define SER32(v) \
 | 
			
		||||
  (unsigned char)( (uint32_t)(v)        & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >>  8) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 16) & 0xff), \
 | 
			
		||||
  (unsigned char)( (uint32_t)(v) >> 24        )
 | 
			
		||||
#define SER32BE(v) \
 | 
			
		||||
  (unsigned char)( (uint32_t)(v) >> 24        ), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 16) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >>  8) & 0xff), \
 | 
			
		||||
  (unsigned char)( (uint32_t)(v)        & 0xff)
 | 
			
		||||
#define SER64(v) \
 | 
			
		||||
  (unsigned char)( (uint64_t)(v)        & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint64_t)(v) >>  8) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint64_t)(v) >> 16) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint64_t)(v) >> 24) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint64_t)(v) >> 32) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint64_t)(v) >> 40) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint64_t)(v) >> 48) & 0xff), \
 | 
			
		||||
  (unsigned char)( (uint64_t)(v) >> 56)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* DDSI_TEST_MEM_SER_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
#include "dds/ddsrt/endian.h"
 | 
			
		||||
#include "dds/ddsi/q_xqos.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_plist_generic.h"
 | 
			
		||||
#include "mem_ser.h"
 | 
			
		||||
 | 
			
		||||
struct desc {
 | 
			
		||||
  const enum pserop desc[20];
 | 
			
		||||
| 
						 | 
				
			
			@ -33,28 +34,9 @@ struct desc_invalid {
 | 
			
		|||
  const unsigned char *ser;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if DDSRT_ENDIAN == DDSRT_BIG_ENDIAN
 | 
			
		||||
#define SER32(v) \
 | 
			
		||||
  (unsigned char)((uint32_t)(v) >> 24), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 16) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 8) & 0xff), \
 | 
			
		||||
  (unsigned char)((uint32_t)(v) & 0xff)
 | 
			
		||||
#define SER32BE(v) SER32(v)
 | 
			
		||||
#else
 | 
			
		||||
#define SER32(v) \
 | 
			
		||||
  (unsigned char)((uint32_t)(v) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 8) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 16) & 0xff), \
 | 
			
		||||
  (unsigned char)((uint32_t)(v) >> 24)
 | 
			
		||||
#define SER32BE(v) \
 | 
			
		||||
  (unsigned char)((uint32_t)(v) >> 24), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 16) & 0xff), \
 | 
			
		||||
  (unsigned char)(((uint32_t)(v) >> 8) & 0xff), \
 | 
			
		||||
  (unsigned char)((uint32_t)(v) & 0xff)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef unsigned char raw[];
 | 
			
		||||
typedef uint32_t raw32[];
 | 
			
		||||
typedef uint64_t raw64[];
 | 
			
		||||
typedef ddsi_octetseq_t oseq;
 | 
			
		||||
 | 
			
		||||
struct desc descs[] = {
 | 
			
		||||
| 
						 | 
				
			
			@ -75,6 +57,7 @@ struct desc descs[] = {
 | 
			
		|||
  { {Xux3,XSTOP}, (raw32){4,5,6},       12, (raw){SER32(4), SER32(5), SER32(6)} },
 | 
			
		||||
  { {Xux4,XSTOP}, (raw32){7,8,9,10},    16, (raw){SER32(7), SER32(8), SER32(9), SER32(10)} },
 | 
			
		||||
  { {Xux5,XSTOP}, (raw32){7,8,9,10,11}, 20, (raw){SER32(7), SER32(8), SER32(9), SER32(10), SER32(11)} },
 | 
			
		||||
  { {Xl,XSTOP},   (raw64){123456789},    8, (raw){SER64(123456789)} },
 | 
			
		||||
  { {XD,XSTOP},   (uint64_t[]){314159265358979324},
 | 
			
		||||
    /* note: fractional part depends on rounding rule used for converting nanoseconds to NTP time
 | 
			
		||||
       Cyclone currently rounds up, so we have to do that too */
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +77,46 @@ struct desc descs[] = {
 | 
			
		|||
    7, (raw){SER32(3), 1,2,3} },
 | 
			
		||||
  { {XQ,XS,XSTOP,XSTOP}, &(ddsi_stringseq_t){2, (char*[]){"tree","flower"}},
 | 
			
		||||
    27, (raw){SER32(2), SER32(5),'t','r','e','e',0, 0,0,0, SER32(7), 'f','l','o','w','e','r',0} },
 | 
			
		||||
  { {Xo,Xl,Xo,Xu,Xo,XSTOP},
 | 
			
		||||
    &(struct{unsigned char a;int64_t b;unsigned char c;uint32_t d;unsigned char e;}){ 1, 2, 3, 4, 5 },
 | 
			
		||||
     25, (raw){1,0,0,0,0,0,0,0,SER64(2),3,0,0,0,SER32(4),5} },
 | 
			
		||||
  { {Xo,XQ,Xo,Xu,Xo,XSTOP,Xo,XSTOP},
 | 
			
		||||
    &(struct{uint8_t b; oseq seq; uint8_t c;})
 | 
			
		||||
      {1, {2, (unsigned char *)(struct{uint8_t a; uint32_t b; uint8_t c;}[])
 | 
			
		||||
              { {0x10, 0x11, 0x12},
 | 
			
		||||
                {0x21, 0x22, 0x23} },
 | 
			
		||||
      }, 0x42 },
 | 
			
		||||
    26,
 | 
			
		||||
    (raw){1, /* pad */0,0,0, SER32(2),
 | 
			
		||||
             0x10, /* pad */0,0,0, SER32(0x11), 0x12,
 | 
			
		||||
             0x21, /* pad */0,0,   SER32(0x22), 0x23,
 | 
			
		||||
          0x42}
 | 
			
		||||
  },
 | 
			
		||||
  { {Xo,XQ,Xo,Xl,Xo,XSTOP,Xo,XSTOP},
 | 
			
		||||
    &(struct{uint8_t b; oseq seq; uint8_t c;})
 | 
			
		||||
      {1, {2, (unsigned char *)(struct{uint8_t a; int64_t b; uint8_t c;}[])
 | 
			
		||||
              { {0x10, 0x11, 0x12},
 | 
			
		||||
                {0x21, 0x22, 0x23} },
 | 
			
		||||
      }, 0x42 },
 | 
			
		||||
    42,
 | 
			
		||||
    (raw){1, /* pad */0,0,0, SER32(2),
 | 
			
		||||
             0x10, /* pad */0,0,0,0,0,0,0, SER64(0x11), 0x12,
 | 
			
		||||
             0x21, /* pad */0,0,0,0,0,0,   SER64(0x22), 0x23,
 | 
			
		||||
          0x42}
 | 
			
		||||
  },
 | 
			
		||||
  { {Xo,XQ,Xo,Xo,XQ,Xo,XSTOP,XSTOP,Xo,XSTOP},
 | 
			
		||||
    &(struct{uint8_t b; oseq seq; uint8_t c;})
 | 
			
		||||
      {1, {2, (unsigned char *)(struct{uint8_t a; uint8_t b; oseq seq;}[])
 | 
			
		||||
        { {0x10, 0x11, { 3, (unsigned char *)(struct{uint8_t a;}[]){ {'a'}, {'b'}, {'c'}}}},
 | 
			
		||||
          {0x21, 0x22, { 2, (unsigned char *)(struct{uint8_t a;}[]){ {'o'}, {'p'}}}}
 | 
			
		||||
        },
 | 
			
		||||
      }, 0x42 },
 | 
			
		||||
    31,
 | 
			
		||||
    (raw){1, /* pad */0,0,0, SER32(2),
 | 
			
		||||
             0x10, 0x11, /* pad */0,0,   SER32(3), 'a','b','c',
 | 
			
		||||
             0x21, 0x22, /* pad */0,0,0, SER32(2), 'o','p',
 | 
			
		||||
          0x42}
 | 
			
		||||
  },
 | 
			
		||||
  { {Xb,XQ,XbPROP,XS,Xo,XSTOP,XSTOP},
 | 
			
		||||
    &(struct{char b; oseq seq;}){1, {5, (unsigned char *)(struct{char b;char *s;uint8_t o;}[]){
 | 
			
		||||
      {0,"apple",1}, {1,"orange",2}, {0,"cherry",3}, {1,"fig",4}, {1,"prune",5}}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -240,7 +263,8 @@ struct desc_invalid descs_invalid[] = {
 | 
			
		|||
      SER32(7), 'o','r','a','n','g','e',0, 2,
 | 
			
		||||
      SER32(4), 'f','i','g',0, 4, 0,0,0,
 | 
			
		||||
      SER32(7), 'p','r','u','n','e',0, 5 // string not terminated
 | 
			
		||||
    } }
 | 
			
		||||
    } },
 | 
			
		||||
  { {XQ,XQ,Xu,XSTOP,XSTOP}, 16, (raw){SER32(2),SER32(1),SER32(31415),SER32(3)} } // nested sequence failure
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
CU_Test (ddsi_plist_generic, invalid_input)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										328
									
								
								src/core/ddsi/tests/security_msg.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								src/core/ddsi/tests/security_msg.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,328 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright(c) 2019 ADLINK Technology Limited and others
 | 
			
		||||
 *
 | 
			
		||||
 * This program and the accompanying materials are made available under the
 | 
			
		||||
 * terms of the Eclipse Public License v. 2.0 which is available at
 | 
			
		||||
 * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
 | 
			
		||||
 * v. 1.0 which is available at
 | 
			
		||||
 * http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "CUnit/Theory.h"
 | 
			
		||||
#include "dds/ddsrt/heap.h"
 | 
			
		||||
#include "dds/ddsrt/string.h"
 | 
			
		||||
#include "dds/ddsi/ddsi_security_msg.h"
 | 
			
		||||
#include "mem_ser.h"
 | 
			
		||||
 | 
			
		||||
static nn_participant_generic_message_t test_msg_in =
 | 
			
		||||
{
 | 
			
		||||
  .message_identity            = { {{.u={1,2,3}},{4}}, 5 },
 | 
			
		||||
  .related_message_identity    = { {{.u={5,4,3}},{2}}, 1 },
 | 
			
		||||
  .destinaton_participant_guid = {  {.u={2,3,4}},{5}     },
 | 
			
		||||
  .destination_endpoint_guid   = {  {.u={3,4,5}},{6}     },
 | 
			
		||||
  .source_endpoint_guid        = {  {.u={4,5,6}},{7}     },
 | 
			
		||||
  .message_class_id            = "testing message",
 | 
			
		||||
  .message_data                = {
 | 
			
		||||
     .n = 4,
 | 
			
		||||
     .tags = (nn_dataholder_t[]) {
 | 
			
		||||
       {
 | 
			
		||||
         .class_id = "holder0",
 | 
			
		||||
         .properties = {
 | 
			
		||||
             .n = 3,
 | 
			
		||||
             .props = (dds_property_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = false,
 | 
			
		||||
                   .name  = "holder0::prop0name",
 | 
			
		||||
                   .value = "holder0::prop0value",
 | 
			
		||||
                 },
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder0::prop1name",
 | 
			
		||||
                   .value = "holder0::prop1value",
 | 
			
		||||
                 },
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = false,
 | 
			
		||||
                   .name  = "holder0::prop2name",
 | 
			
		||||
                   .value = "holder0::prop2value",
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
         .binary_properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_binaryproperty_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = false,
 | 
			
		||||
                   .name  = "holder0::bprop0name",
 | 
			
		||||
                   .value = { 2, (unsigned char[]){ 1, 2 } },
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
       },
 | 
			
		||||
       {
 | 
			
		||||
         .class_id = "holder1",
 | 
			
		||||
         .properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_property_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder1::prop0name",
 | 
			
		||||
                   .value = "holder1::prop0value",
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
         .binary_properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_binaryproperty_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder1::bprop0name",
 | 
			
		||||
                   .value = { 3, (unsigned char[]){ 1, 2, 3 } },
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
       },
 | 
			
		||||
       {
 | 
			
		||||
         .class_id = "holder2",
 | 
			
		||||
         .properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_property_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = false,
 | 
			
		||||
                   .name  = "holder2::prop0name",
 | 
			
		||||
                   .value = "holder2::prop0value",
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
         .binary_properties = {
 | 
			
		||||
             .n = 3,
 | 
			
		||||
             .props = (dds_binaryproperty_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder2::bprop0name",
 | 
			
		||||
                   .value = { 3, (unsigned char[]){ 1, 2, 3 } },
 | 
			
		||||
                 },
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = false,
 | 
			
		||||
                   .name  = "holder2::bprop1name",
 | 
			
		||||
                   .value = { 4, (unsigned char[]){ 1, 2, 3, 4 } },
 | 
			
		||||
                 },
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder2::bprop2name",
 | 
			
		||||
                   .value = { 5, (unsigned char[]){ 1, 2, 3, 4, 5 } },
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
       },
 | 
			
		||||
       {
 | 
			
		||||
         .class_id = "holder3",
 | 
			
		||||
         .properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_property_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = false,
 | 
			
		||||
                   .name  = "holder3::prop0name",
 | 
			
		||||
                   .value = "holder3::prop0value",
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
         .binary_properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_binaryproperty_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = false,
 | 
			
		||||
                   .name  = "holder3::bprop0name",
 | 
			
		||||
                   .value = { 3, (unsigned char[]){ 1, 2, 3 } },
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
       },
 | 
			
		||||
     },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Same as test_msg_in, excluding the non-propagated properties. */
 | 
			
		||||
static nn_participant_generic_message_t test_msg_out =
 | 
			
		||||
{
 | 
			
		||||
  .message_identity            = { {{.u={1,2,3}},{4}}, 5 },
 | 
			
		||||
  .related_message_identity    = { {{.u={5,4,3}},{2}}, 1 },
 | 
			
		||||
  .destinaton_participant_guid = {  {.u={2,3,4}},{5}     },
 | 
			
		||||
  .destination_endpoint_guid   = {  {.u={3,4,5}},{6}     },
 | 
			
		||||
  .source_endpoint_guid        = {  {.u={4,5,6}},{7}     },
 | 
			
		||||
  .message_class_id            = "testing message",
 | 
			
		||||
  .message_data                = {
 | 
			
		||||
     .n = 4,
 | 
			
		||||
     .tags = (nn_dataholder_t[]) {
 | 
			
		||||
       {
 | 
			
		||||
         .class_id = "holder0",
 | 
			
		||||
         .properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_property_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder0::prop1name",
 | 
			
		||||
                   .value = "holder0::prop1value",
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
         .binary_properties = {
 | 
			
		||||
             .n = 0,
 | 
			
		||||
             .props = NULL
 | 
			
		||||
         },
 | 
			
		||||
       },
 | 
			
		||||
       {
 | 
			
		||||
         .class_id = "holder1",
 | 
			
		||||
         .properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_property_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder1::prop0name",
 | 
			
		||||
                   .value = "holder1::prop0value",
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
         .binary_properties = {
 | 
			
		||||
             .n = 1,
 | 
			
		||||
             .props = (dds_binaryproperty_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder1::bprop0name",
 | 
			
		||||
                   .value = { 3, (unsigned char[]){ 1, 2, 3 } },
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
       },
 | 
			
		||||
       {
 | 
			
		||||
         .class_id = "holder2",
 | 
			
		||||
         .properties = {
 | 
			
		||||
             .n = 0,
 | 
			
		||||
             .props = NULL,
 | 
			
		||||
         },
 | 
			
		||||
         .binary_properties = {
 | 
			
		||||
             .n = 2,
 | 
			
		||||
             .props = (dds_binaryproperty_t[]) {
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder2::bprop0name",
 | 
			
		||||
                   .value = { 3, (unsigned char[]){ 1, 2, 3 } },
 | 
			
		||||
                 },
 | 
			
		||||
                 {
 | 
			
		||||
                   .propagate = true,
 | 
			
		||||
                   .name  = "holder2::bprop2name",
 | 
			
		||||
                   .value = { 5, (unsigned char[]){ 1, 2, 3, 4, 5 } },
 | 
			
		||||
                 },
 | 
			
		||||
             }
 | 
			
		||||
         },
 | 
			
		||||
       },
 | 
			
		||||
       {
 | 
			
		||||
         .class_id = "holder3",
 | 
			
		||||
         .properties = {
 | 
			
		||||
             .n = 0,
 | 
			
		||||
             .props = NULL,
 | 
			
		||||
         },
 | 
			
		||||
         .binary_properties = {
 | 
			
		||||
             .n = 0,
 | 
			
		||||
             .props = NULL,
 | 
			
		||||
         },
 | 
			
		||||
       },
 | 
			
		||||
     },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* The cdr of test_msg_out. */
 | 
			
		||||
static unsigned char test_msg_ser[] = {
 | 
			
		||||
  SER32BE(1), SER32BE(2), SER32BE(3), SER32BE(4), SER64(5),
 | 
			
		||||
  SER32BE(5), SER32BE(4), SER32BE(3), SER32BE(2), SER64(1),
 | 
			
		||||
  SER32BE(2), SER32BE(3), SER32BE(4), SER32BE(5),
 | 
			
		||||
  SER32BE(3), SER32BE(4), SER32BE(5), SER32BE(6),
 | 
			
		||||
  SER32BE(4), SER32BE(5), SER32BE(6), SER32BE(7),
 | 
			
		||||
  SER32(16), 't','e','s','t','i','n','g',' ','m','e','s','s','a','g','e',0,
 | 
			
		||||
    SER32(4),
 | 
			
		||||
    /* dataholder 0 */
 | 
			
		||||
    SER32(8), 'h','o','l','d','e','r','0',0,
 | 
			
		||||
    SER32(1),
 | 
			
		||||
      SER32(19), 'h','o','l','d','e','r','0',':',':','p','r','o','p','1','n','a','m','e',0,/* pad */0,
 | 
			
		||||
      SER32(20), 'h','o','l','d','e','r','0',':',':','p','r','o','p','1','v','a','l','u','e',0,
 | 
			
		||||
    SER32(0),
 | 
			
		||||
    /* dataholder 1 */
 | 
			
		||||
    SER32(8), 'h','o','l','d','e','r','1',0,
 | 
			
		||||
    SER32(1),
 | 
			
		||||
      SER32(19), 'h','o','l','d','e','r','1',':',':','p','r','o','p','0','n','a','m','e',0,/* pad */0,
 | 
			
		||||
      SER32(20), 'h','o','l','d','e','r','1',':',':','p','r','o','p','0','v','a','l','u','e',0,
 | 
			
		||||
    SER32(1),
 | 
			
		||||
      SER32(20), 'h','o','l','d','e','r','1',':',':','b','p','r','o','p','0','n','a','m','e',0,
 | 
			
		||||
      SER32(3), 1,2,3,  /* pad */0,
 | 
			
		||||
    /* dataholder 2 */
 | 
			
		||||
    SER32(8), 'h','o','l','d','e','r','2',0,
 | 
			
		||||
    SER32(0),
 | 
			
		||||
    SER32(2),
 | 
			
		||||
      SER32(20), 'h','o','l','d','e','r','2',':',':','b','p','r','o','p','0','n','a','m','e',0,
 | 
			
		||||
      SER32(3), 1,2,3,  /* pad */0,
 | 
			
		||||
      SER32(20), 'h','o','l','d','e','r','2',':',':','b','p','r','o','p','2','n','a','m','e',0,
 | 
			
		||||
      SER32(5), 1,2,3,4,5,  /* pad */0,0,0,
 | 
			
		||||
    /* dataholder 2 */
 | 
			
		||||
    SER32(8), 'h','o','l','d','e','r','3',0,
 | 
			
		||||
    SER32(0),
 | 
			
		||||
    SER32(0)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
CU_Test (ddsi_security_msg, serializer)
 | 
			
		||||
{
 | 
			
		||||
  nn_participant_generic_message_t msg_in;
 | 
			
		||||
  nn_participant_generic_message_t msg_ser;
 | 
			
		||||
  unsigned char *data = NULL;
 | 
			
		||||
  dds_return_t ret;
 | 
			
		||||
  size_t len;
 | 
			
		||||
  bool equal;
 | 
			
		||||
 | 
			
		||||
  /* Create the message (normally with various arguments). */
 | 
			
		||||
  nn_participant_generic_message_init(
 | 
			
		||||
              &msg_in,
 | 
			
		||||
              &test_msg_in.message_identity.source_guid,
 | 
			
		||||
               test_msg_in.message_identity.sequence_number,
 | 
			
		||||
              &test_msg_in.destinaton_participant_guid,
 | 
			
		||||
              &test_msg_in.destination_endpoint_guid,
 | 
			
		||||
              &test_msg_in.source_endpoint_guid,
 | 
			
		||||
               test_msg_in.message_class_id,
 | 
			
		||||
              &test_msg_in.message_data,
 | 
			
		||||
              &test_msg_in.related_message_identity);
 | 
			
		||||
 | 
			
		||||
  /* Check creation result. */
 | 
			
		||||
  equal = plist_equal_generic(&msg_in, &test_msg_in, pserop_participant_generic_message);
 | 
			
		||||
  CU_ASSERT_FATAL(equal == true);
 | 
			
		||||
 | 
			
		||||
  /* Serialize the message. */
 | 
			
		||||
  ret = nn_participant_generic_message_serialize(&msg_in, &data, &len);
 | 
			
		||||
  CU_ASSERT_FATAL (ret == DDS_RETCODE_OK);
 | 
			
		||||
  CU_ASSERT_PTR_NOT_NULL_FATAL(data);
 | 
			
		||||
  CU_ASSERT(len > 0);
 | 
			
		||||
 | 
			
		||||
  /* Check serialization result. */
 | 
			
		||||
  size_t cmpsize = (len < sizeof(test_msg_ser)) ? len : sizeof(test_msg_ser);
 | 
			
		||||
  if (memcmp (data, test_msg_ser, cmpsize) != 0)
 | 
			
		||||
  {
 | 
			
		||||
    printf ("memcmp(%d)\n", (int)cmpsize);
 | 
			
		||||
    for (size_t k = 0; k < cmpsize; k++)
 | 
			
		||||
      printf ("  %3zu  %02x  %02x (%c) %s\n", k, data[k], test_msg_ser[k],
 | 
			
		||||
              ((test_msg_ser[k] >= '0') && (test_msg_ser[k] <= 'z')) ? test_msg_ser[k] : ' ',
 | 
			
		||||
              (data[k] == test_msg_ser[k]) ? "" : "<--");
 | 
			
		||||
    CU_ASSERT (!(bool)"memcmp");
 | 
			
		||||
  }
 | 
			
		||||
  CU_ASSERT_FATAL (len == sizeof(test_msg_ser));
 | 
			
		||||
 | 
			
		||||
  /* Deserialize the message. */
 | 
			
		||||
  ret = nn_participant_generic_message_deseralize(&msg_ser, data, len, false);
 | 
			
		||||
  CU_ASSERT_FATAL (ret == DDS_RETCODE_OK);
 | 
			
		||||
 | 
			
		||||
  /* Check deserialization result. */
 | 
			
		||||
  equal = plist_equal_generic(&msg_ser, &test_msg_out, pserop_participant_generic_message);
 | 
			
		||||
  CU_ASSERT_FATAL(equal == true);
 | 
			
		||||
 | 
			
		||||
  /* Cleanup. */
 | 
			
		||||
  nn_participant_generic_message_deinit(&msg_in);
 | 
			
		||||
  nn_participant_generic_message_deinit(&msg_ser);
 | 
			
		||||
  ddsrt_free(data);
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue