Encoding preparations (#329)

* Payload encoding/decoding preparations.

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>

* Sub-message encoding/decoding preparations.

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>

* RTPS message encoding/decoding preparations.

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>

* Removed redundant destination acquiring.

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>

* Refactored secure writing of RTPS messages slightly.

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>
This commit is contained in:
martinbremmer 2019-12-06 16:50:31 +01:00 committed by eboasson
parent 30bd6e4c1c
commit 66c0d87886
13 changed files with 2134 additions and 121 deletions

View file

@ -12,16 +12,40 @@
#ifndef DDSI_OMG_SECURITY_H #ifndef DDSI_OMG_SECURITY_H
#define DDSI_OMG_SECURITY_H #define DDSI_OMG_SECURITY_H
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_plist.h" #include "dds/ddsi/q_plist.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_globals.h"
#include "dds/ddsi/q_radmin.h"
#include "dds/ddsi/q_xmsg.h"
#if defined (__cplusplus) #if defined (__cplusplus)
extern "C" { extern "C" {
#endif #endif
typedef enum {
NN_RTPS_MSG_STATE_ERROR,
NN_RTPS_MSG_STATE_PLAIN,
NN_RTPS_MSG_STATE_ENCODED
} nn_rtps_msg_state_t;
#ifdef DDSI_INCLUDE_SECURITY #ifdef DDSI_INCLUDE_SECURITY
typedef struct nn_msg_sec_info {
int64_t src_pp_handle;
int64_t dst_pp_handle;
bool use_rtps_encoding;
} nn_msg_sec_info_t;
/**
* @brief Check if any participant has security enabled.
*
* @returns bool
* @retval true Some participant is secure
* @retval false No participant is not secure
*/
bool q_omg_security_enabled(void);
/** /**
* @brief Check if security is enabled for the participant. * @brief Check if security is enabled for the participant.
* *
@ -33,6 +57,26 @@ extern "C" {
*/ */
bool q_omg_participant_is_secure(const struct participant *pp); bool q_omg_participant_is_secure(const struct participant *pp);
/**
* @brief Get the security handle of the given local participant.
*
* @param[in] pp Participant to check if it is secure.
*
* @returns int64_t
* @retval Local participant security handle
*/
int64_t q_omg_security_get_local_participant_handle(struct participant *pp);
/**
* @brief Get the security handle of the given remote participant.
*
* @param[in] proxypp Participant to check if it is secure.
*
* @returns int64_t
* @retval Remote participant security handle
*/
int64_t q_omg_security_get_remote_participant_handle(struct proxy_participant *proxypp);
/** /**
* @brief Get security info flags of the given writer. * @brief Get security info flags of the given writer.
* *
@ -107,12 +151,355 @@ unsigned determine_publication_writer(const struct writer *wr);
* @retval true The proxy participant may be deleted. * @retval true The proxy participant may be deleted.
* @retval false The proxy participant may not be deleted by this writer. * @retval false The proxy participant may not be deleted by this writer.
*/ */
bool allow_proxy_participant_deletion(struct q_globals * const gv, const struct ddsi_guid *guid, const ddsi_entityid_t pwr_entityid); bool
is_proxy_participant_deletion_allowed(
struct q_globals * const gv,
const struct ddsi_guid *guid,
const ddsi_entityid_t pwr_entityid);
/**
* @brief Determine if the messages, related to the given remote
* entity, are RTPS protected or not.
*
* @param[in] proxy_pp Related proxy participant.
* @param[in] entityid ID of the entity to check.
*
* @returns bool
* @retval true The entity messages are RTPS protected.
* @retval false The entity messages are not RTPS protected.
*/
bool
q_omg_security_is_remote_rtps_protected(
struct proxy_participant *proxy_pp,
ddsi_entityid_t entityid);
/**
* @brief Determine if the messages, related to the given local
* entity, are RTPS protected or not.
*
* @param[in] pp Related participant.
* @param[in] entityid ID of the entity to check.
*
* @returns bool
* @retval true The entity messages are RTPS protected.
* @retval false The entity messages are not RTPS protected.
*/
bool
q_omg_security_is_local_rtps_protected(
struct participant *pp,
ddsi_entityid_t entityid);
/**
* @brief Set security information, depending on plist, into the given
* proxy participant.
*
* @param[in] proxypp Proxy participant to set security info on.
* @param[in] plist Paramater list, possibly contains security info.
*/
void
set_proxy_participant_security_info(
struct proxy_participant *proxypp,
const nn_plist_t *plist);
/**
* @brief Set security information, depending on plist and proxy participant,
* into the given proxy reader.
*
* @param[in] prd Proxy reader to set security info on.
* @param[in] plist Paramater list, possibly contains security info.
*/
void
set_proxy_reader_security_info(
struct proxy_reader *prd,
const nn_plist_t *plist);
/**
* @brief Set security information, depending on plist and proxy participant,
* into the given proxy writer.
*
* @param[in] pwr Proxy writer to set security info on.
* @param[in] plist Paramater list, possibly contains security info.
*/
void
set_proxy_writer_security_info(
struct proxy_writer *pwr,
const nn_plist_t *plist);
/**
* @brief Encode RTPS message.
*
* @param[in] src_handle Security handle of data source.
* @param[in] src_guid GUID of the entity data source.
* @param[in] src_buf Original RTPS message.
* @param[in] src_len Original RTPS message size.
* @param[out] dst_buf Encoded RTPS message.
* @param[out] dst_len Encoded RTPS message size.
* @param[in] dst_handle Security handle of data destination.
*
* @returns bool
* @retval true Encoding succeeded.
* @retval false Encoding failed.
*/
bool
q_omg_security_encode_rtps_message(
int64_t src_handle,
ddsi_guid_t *src_guid,
const unsigned char *src_buf,
const unsigned int src_len,
unsigned char **dst_buf,
unsigned int *dst_len,
int64_t dst_handle);
/**
* @brief Encode payload when necessary.
*
* When encoding is necessary, *buf will be allocated and the vec contents
* will change to point to that buffer.
* It is expected that the vec contents is always aliased.
*
* If no encoding is necessary, nothing changes.
*
* encoding( not needed) -> return( true), vec(untouched), buf(NULL)
* encoding(needed&success) -> return( true), vec( buf(new))
* encoding(needed&failure) -> return(false), vec(untouched), buf(NULL)
*
* @param[in] wr Writer that writes the payload.
* @param[in,out] vec An iovec that contains the payload.
* @param[out] buf Buffer to contain the encoded payload.
*
* @returns bool
* @retval true Encoding succeeded or not necessary. Either way, vec
* contains the payload that should be send.
* @retval false Encoding was necessary, but failed.
*/
bool
encode_payload(
struct writer *wr,
ddsrt_iovec_t *vec,
unsigned char **buf);
/**
* @brief Decode the payload of a Data submessage.
*
* When decoding is necessary, the payloadp memory will be replaced
* by the decoded payload. This means that the original submessage
* now contains payload that can be deserialized.
*
* If no decoding is necessary, nothing changes.
*
* @param[in] gv Global information.
* @param[in] sampleinfo Sample information.
* @param[in,out] payloadp Pointer to payload memory.
* @param[in] payloadsz Size of payload.
* @param[in,out] submsg_len Size of submessage.
*
* @returns bool
* @retval true Decoding succeeded or not necessary. Either way, payloadp
* contains the data that should be deserialized.
* @retval false Decoding was necessary, but failed.
*/
bool
decode_Data(
const struct q_globals *gv,
struct nn_rsample_info *sampleinfo,
unsigned char *payloadp,
uint32_t payloadsz,
size_t *submsg_len);
/**
* @brief Decode the payload of a DataFrag submessage.
*
* When decoding is necessary, the payloadp memory will be replaced
* by the decoded payload. This means that the original submessage
* now contains payload that can be deserialized.
*
* If no decoding is necessary, nothing changes.
*
* @param[in] gv Global information.
* @param[in] sampleinfo Sample information.
* @param[in,out] payloadp Pointer to payload memory.
* @param[in] payloadsz Size of payload.
* @param[in,out] submsg_len Size of submessage.
*
* @returns bool
* @retval true Decoding succeeded or not necessary. Either way, payloadp
* contains the data that should be deserialized.
* @retval false Decoding was necessary, but failed.
*/
bool
decode_DataFrag(
const struct q_globals *gv,
struct nn_rsample_info *sampleinfo,
unsigned char *payloadp,
uint32_t payloadsz,
size_t *submsg_len);
/**
* @brief Encode datareader submessage when necessary.
*
* When encoding is necessary, the original submessage will be replaced
* by a new encoded submessage.
* If the encoding fails, the original submessage will be removed.
*
* If no encoding is necessary, nothing changes.
*
* @param[in,out] msg Complete message.
* @param[in,out] sm_marker Submessage location within message.
* @param[in] pwr Writer for which the message is intended.
* @param[in] rd_guid Origin reader guid.
*/
void
encode_datareader_submsg(
struct nn_xmsg *msg,
struct nn_xmsg_marker sm_marker,
struct proxy_writer *pwr,
const struct ddsi_guid *rd_guid);
/**
* @brief Encode datawriter submessage when necessary.
*
* When encoding is necessary, the original submessage will be replaced
* by a new encoded submessage.
* If the encoding fails, the original submessage will be removed.
*
* If no encoding is necessary, nothing changes.
*
* @param[in,out] msg Complete message.
* @param[in,out] sm_marker Submessage location within message.
* @param[in] wr Origin writer guid.
*/
void
encode_datawriter_submsg(
struct nn_xmsg *msg,
struct nn_xmsg_marker sm_marker,
struct writer *wr);
/**
* @brief Check if given submessage is properly decoded.
*
* When decoding is necessary, it should be checked if a plain submessage was
* actually decoded. Otherwise data can be injected just by inserting a plain
* submessage directly.
*
* @param[in] e Entity information.
* @param[in] c Proxy endpoint information.
* @param[in] proxypp Related proxy participant.
* @param[in] rst Receiver information.
* @param[in] prev_smid Previously handled submessage ID.
*
* @returns bool
* @retval true Decoding succeeded or was not necessary.
* @retval false Decoding was necessary, but not detected.
*/
bool
validate_msg_decoding(
const struct entity_common *e,
const struct proxy_endpoint_common *c,
struct proxy_participant *proxypp,
struct receiver_state *rst,
SubmessageKind_t prev_smid);
/**
* @brief Decode not only SecPrefix, but also the SecBody and SecPostfix
* sub-messages.
*
* When encrypted, the original SecBody will be replaced by the decrypted
* submessage. Then the normal sequence can continue as if there was no
* encrypted data.
*
* @param[in] rst Receiver information.
* @param[in,out] submsg Pointer to SecPrefix/(SecBody|Submsg)/SecPostfix.
* @param[in] submsg_size Size of SecPrefix submessage.
* @param[in] msg_end End of the complete message.
* @param[in] src_prefix Prefix of the source entity.
* @param[in] dst_prefix Prefix of the destination entity.
* @param[in] byteswap Do the bytes need swapping?
*
* @returns int
* @retval >= 0 Decoding succeeded.
* @retval < 0 Decoding failed.
*/
int
decode_SecPrefix(
struct receiver_state *rst,
unsigned char *submsg,
size_t submsg_size,
unsigned char * const msg_end,
const ddsi_guid_prefix_t * const src_prefix,
const ddsi_guid_prefix_t * const dst_prefix,
int byteswap);
/**
* @brief Decode the RTPS message.
*
* When encrypted, the original buffers and information will be replaced
* by the decrypted RTPS message. Then the normal sequence can continue
* as if there was no encrypted data.
*
* @param[in] ts1 Thread information.
* @param[in] gv Global information.
* @param[in,out] rmsg Message information.
* @param[in,out] hdr Message header.
* @param[in,out] buff Message buffer.
* @param[in,out] sz Message size.
* @param[in] rbpool Buffers pool.
* @param[in] isstream Is message a stream variant?
*
* @returns nn_rtps_msg_state_t
* @retval NN_RTPS_MSG_STATE_PLAIN No decoding was necessary.
* @retval NN_RTPS_MSG_STATE_ENCODED Decoding succeeded.
* @retval NN_RTPS_MSG_STATE_ERROR Decoding failed.
*/
nn_rtps_msg_state_t
decode_rtps_message(
struct thread_state1 * const ts1,
struct q_globals *gv,
struct nn_rmsg **rmsg,
Header_t **hdr,
unsigned char **buff,
ssize_t *sz,
struct nn_rbufpool *rbpool,
bool isstream);
/**
* @brief Send the RTPS message securely.
*
* @param[in] conn Connection to use.
* @param[in] dst Possible destination information.
* @param[in] niov Number of io vectors.
* @param[in] iov Array of io vectors.
* @param[in] flags Connection write flags.
* @param[in,out] msg_len Submessage containing length.
* @param[in] dst_one Is there only one specific destination?
* @param[in] sec_info Security information for handles.
* @param[in] conn_write_cb Function to call to do the actual writing.
*
* @returns ssize_t
* @retval negative/zero Something went wrong.
* @retval positive Secure writing succeeded.
*/
ssize_t
secure_conn_write(
ddsi_tran_conn_t conn,
const nn_locator_t *dst,
size_t niov,
const ddsrt_iovec_t *iov,
uint32_t flags,
MsgLen_t *msg_len,
bool dst_one,
nn_msg_sec_info_t *sec_info,
ddsi_tran_write_fn_t conn_write_cb);
#else /* DDSI_INCLUDE_SECURITY */ #else /* DDSI_INCLUDE_SECURITY */
#include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_unused.h"
inline bool
q_omg_security_enabled(void)
{
return false;
}
inline bool inline bool
q_omg_participant_is_secure( q_omg_participant_is_secure(
UNUSED_ARG(const struct participant *pp)) UNUSED_ARG(const struct participant *pp))
@ -135,7 +522,7 @@ determine_publication_writer(
} }
inline bool inline bool
allow_proxy_participant_deletion( is_proxy_participant_deletion_allowed(
UNUSED_ARG(struct q_globals * const gv), UNUSED_ARG(struct q_globals * const gv),
UNUSED_ARG(const struct ddsi_guid *guid), UNUSED_ARG(const struct ddsi_guid *guid),
UNUSED_ARG(const ddsi_entityid_t pwr_entityid)) UNUSED_ARG(const ddsi_entityid_t pwr_entityid))
@ -143,6 +530,106 @@ allow_proxy_participant_deletion(
return true; return true;
} }
inline void
set_proxy_participant_security_info(
UNUSED_ARG(struct proxy_participant *prd),
UNUSED_ARG(const nn_plist_t *plist))
{
}
inline void
set_proxy_reader_security_info(
UNUSED_ARG(struct proxy_reader *prd),
UNUSED_ARG(const nn_plist_t *plist))
{
}
inline void
set_proxy_writer_security_info(
UNUSED_ARG(struct proxy_writer *pwr),
UNUSED_ARG(const nn_plist_t *plist))
{
}
inline bool
decode_Data(
UNUSED_ARG(const struct q_globals *gv),
UNUSED_ARG(struct nn_rsample_info *sampleinfo),
UNUSED_ARG(unsigned char *payloadp),
UNUSED_ARG(uint32_t payloadsz),
UNUSED_ARG(size_t *submsg_len))
{
return true;
}
inline bool
decode_DataFrag(
UNUSED_ARG(const struct q_globals *gv),
UNUSED_ARG(struct nn_rsample_info *sampleinfo),
UNUSED_ARG(unsigned char *payloadp),
UNUSED_ARG(uint32_t payloadsz),
UNUSED_ARG(size_t *submsg_len))
{
return true;
}
inline void
encode_datareader_submsg(
UNUSED_ARG(struct nn_xmsg *msg),
UNUSED_ARG(struct nn_xmsg_marker sm_marker),
UNUSED_ARG(struct proxy_writer *pwr),
UNUSED_ARG(const struct ddsi_guid *rd_guid))
{
}
inline void
encode_datawriter_submsg(
UNUSED_ARG(struct nn_xmsg *msg),
UNUSED_ARG(struct nn_xmsg_marker sm_marker),
UNUSED_ARG(struct writer *wr))
{
}
inline bool
validate_msg_decoding(
UNUSED_ARG(const struct entity_common *e),
UNUSED_ARG(const struct proxy_endpoint_common *c),
UNUSED_ARG(struct proxy_participant *proxypp),
UNUSED_ARG(struct receiver_state *rst),
UNUSED_ARG(SubmessageKind_t prev_smid))
{
return true;
}
inline int
decode_SecPrefix(
UNUSED_ARG(struct receiver_state *rst),
UNUSED_ARG(unsigned char *submsg),
UNUSED_ARG(size_t submsg_size),
UNUSED_ARG(unsigned char * const msg_end),
UNUSED_ARG(const ddsi_guid_prefix_t * const src_prefix),
UNUSED_ARG(const ddsi_guid_prefix_t * const dst_prefix),
UNUSED_ARG(int byteswap))
{
/* Just let the parsing ignore the security sub-messages. */
return true;
}
inline nn_rtps_msg_state_t
decode_rtps_message(
UNUSED_ARG(struct thread_state1 * const ts1),
UNUSED_ARG(struct q_globals *gv),
UNUSED_ARG(struct nn_rmsg **rmsg),
UNUSED_ARG(Header_t **hdr),
UNUSED_ARG(unsigned char **buff),
UNUSED_ARG(ssize_t *sz),
UNUSED_ARG(struct nn_rbufpool *rbpool),
UNUSED_ARG(bool isstream))
{
return NN_RTPS_MSG_STATE_PLAIN;
}
#endif /* DDSI_INCLUDE_SECURITY */ #endif /* DDSI_INCLUDE_SECURITY */
#if defined (__cplusplus) #if defined (__cplusplus)

View file

@ -16,6 +16,7 @@
#include "dds/ddsrt/avl.h" #include "dds/ddsrt/avl.h"
#include "dds/ddsrt/sync.h" #include "dds/ddsrt/sync.h"
#include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_rtps.h"
#include "dds/ddsi/q_plist.h"
#include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_protocol.h"
#include "dds/ddsi/q_lat_estim.h" #include "dds/ddsi/q_lat_estim.h"
#include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_ephash.h"
@ -314,6 +315,9 @@ struct proxy_participant
unsigned proxypp_have_spdp: 1; unsigned proxypp_have_spdp: 1;
unsigned proxypp_have_cm: 1; unsigned proxypp_have_cm: 1;
unsigned owns_lease: 1; unsigned owns_lease: 1;
#ifdef DDSI_INCLUDE_SECURITY
nn_security_info_t security_info;
#endif
}; };
/* Representing proxy subscriber & publishers as "groups": until DDSI2 /* Representing proxy subscriber & publishers as "groups": until DDSI2
@ -341,6 +345,9 @@ struct proxy_endpoint_common
ddsi_guid_t group_guid; /* 0:0:0:0 if not available */ ddsi_guid_t group_guid; /* 0:0:0:0 if not available */
nn_vendorid_t vendor; /* cached from proxypp->vendor */ nn_vendorid_t vendor; /* cached from proxypp->vendor */
seqno_t seq; /* sequence number of most recent SEDP message */ seqno_t seq; /* sequence number of most recent SEDP message */
#ifdef DDSI_INCLUDE_SECURITY
nn_security_info_t security_info;
#endif
}; };
struct proxy_writer { struct proxy_writer {

View file

@ -162,6 +162,12 @@ typedef enum SubmessageKind {
SMID_HEARTBEAT_FRAG = 0x13, SMID_HEARTBEAT_FRAG = 0x13,
SMID_DATA = 0x15, SMID_DATA = 0x15,
SMID_DATA_FRAG = 0x16, SMID_DATA_FRAG = 0x16,
/* security-specific sub messages */
SMID_SEC_BODY = 0x30,
SMID_SEC_PREFIX = 0x31,
SMID_SEC_POSTFIX = 0x32,
SMID_SRTPS_PREFIX = 0x33,
SMID_SRTPS_POSTFIX = 0x34,
/* vendor-specific sub messages (0x80 .. 0xff) */ /* vendor-specific sub messages (0x80 .. 0xff) */
SMID_PT_INFO_CONTAINER = 0x80, SMID_PT_INFO_CONTAINER = 0x80,
SMID_PT_MSG_LEN = 0x81, SMID_PT_MSG_LEN = 0x81,

View file

@ -102,10 +102,11 @@ struct nn_rmsg {
#define NN_RMSG_PAYLOADOFF(m, o) (NN_RMSG_PAYLOAD (m) + (o)) #define NN_RMSG_PAYLOADOFF(m, o) (NN_RMSG_PAYLOAD (m) + (o))
struct receiver_state { struct receiver_state {
ddsi_guid_prefix_t src_guid_prefix; /* 12 */ ddsi_guid_prefix_t src_guid_prefix; /* 12 */
ddsi_guid_prefix_t dst_guid_prefix; /* 12 */ ddsi_guid_prefix_t dst_guid_prefix; /* 12 */
struct addrset *reply_locators; /* 4/8 */ struct addrset *reply_locators; /* 4/8 */
int forme; /* 4 */ uint32_t forme:1; /* 4 */
uint32_t rtps_encoded:1; /* - */
nn_vendorid_t vendor; /* 2 */ nn_vendorid_t vendor; /* 2 */
nn_protocol_version_t protocol_version; /* 2 => 44/48 */ nn_protocol_version_t protocol_version; /* 2 => 44/48 */
ddsi_tran_conn_t conn; /* Connection for request */ ddsi_tran_conn_t conn; /* Connection for request */

View file

@ -46,8 +46,8 @@ DDS_EXPORT dds_return_t xeventq_start (struct xeventq *evq, const char *name); /
DDS_EXPORT void xeventq_stop (struct xeventq *evq); DDS_EXPORT void xeventq_stop (struct xeventq *evq);
DDS_EXPORT void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg); DDS_EXPORT void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg);
DDS_EXPORT void qxev_pwr_entityid (struct proxy_writer * pwr, ddsi_guid_prefix_t * id); DDS_EXPORT void qxev_pwr_entityid (struct proxy_writer * pwr, const ddsi_guid_t *guid);
DDS_EXPORT void qxev_prd_entityid (struct proxy_reader * prd, ddsi_guid_prefix_t * id); DDS_EXPORT void qxev_prd_entityid (struct proxy_reader * prd, const ddsi_guid_t *guid);
/* Returns 1 if queued, 0 otherwise (no point in returning the /* Returns 1 if queued, 0 otherwise (no point in returning the
event, you can't do anything with it anyway) */ event, you can't do anything with it anyway) */

View file

@ -26,6 +26,8 @@ struct ddsi_serdata;
struct addrset; struct addrset;
struct proxy_reader; struct proxy_reader;
struct proxy_writer; struct proxy_writer;
struct writer;
struct participant;
struct nn_prismtech_participant_version_info; struct nn_prismtech_participant_version_info;
struct nn_xmsgpool; struct nn_xmsgpool;
@ -54,10 +56,11 @@ void nn_xmsgpool_free (struct nn_xmsgpool *pool);
/* To allocate a new xmsg from the pool; if expected_size is NOT /* To allocate a new xmsg from the pool; if expected_size is NOT
exceeded, no reallocs will be performed, else the address of the exceeded, no reallocs will be performed, else the address of the
xmsg may change because of reallocing when appending to it. */ xmsg may change because of reallocing when appending to it. */
struct nn_xmsg *nn_xmsg_new (struct nn_xmsgpool *pool, const ddsi_guid_prefix_t *src_guid_prefix, size_t expected_size, enum nn_xmsg_kind kind); struct nn_xmsg *nn_xmsg_new (struct nn_xmsgpool *pool, const ddsi_guid_t *src_guid, struct participant *pp, size_t expected_size, enum nn_xmsg_kind kind);
/* For sending to a particular destination (participant) */ /* For sending to a particular destination (participant) */
void nn_xmsg_setdst1 (struct nn_xmsg *m, const ddsi_guid_prefix_t *gp, const nn_locator_t *addr); void nn_xmsg_setdst1 (struct q_globals *gv, struct nn_xmsg *m, const ddsi_guid_prefix_t *gp, const nn_locator_t *addr);
bool nn_xmsg_getdst1prefix (struct nn_xmsg *m, ddsi_guid_prefix_t *gp);
/* For sending to a particular proxy reader; this is a convenience /* For sending to a particular proxy reader; this is a convenience
routine that extracts a suitable address from the proxy reader's routine that extracts a suitable address from the proxy reader's
@ -114,7 +117,13 @@ void nn_xmsg_guid_seq_fragid (const struct nn_xmsg *m, ddsi_guid_t *wrguid, seqn
void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker marker); void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
void *nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz); void *nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz);
void nn_xmsg_shrink (struct nn_xmsg *m, struct nn_xmsg_marker marker, size_t sz); void nn_xmsg_shrink (struct nn_xmsg *m, struct nn_xmsg_marker marker, size_t sz);
void nn_xmsg_serdata (struct nn_xmsg *m, struct ddsi_serdata *serdata, size_t off, size_t len); void nn_xmsg_serdata (struct nn_xmsg *m, struct ddsi_serdata *serdata, size_t off, size_t len, struct writer *wr);
#ifdef DDSI_INCLUDE_SECURITY
size_t nn_xmsg_submsg_size (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
void nn_xmsg_submsg_remove (struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker);
void nn_xmsg_submsg_replace (struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker, unsigned char *new_submsg, size_t new_len);
void nn_xmsg_submsg_append_refd_payload (struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker);
#endif
void nn_xmsg_submsg_setnext (struct nn_xmsg *msg, struct nn_xmsg_marker marker); void nn_xmsg_submsg_setnext (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, SubmessageKind_t smkind); void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, SubmessageKind_t smkind);
void nn_xmsg_add_timestamp (struct nn_xmsg *m, nn_wctime_t t); void nn_xmsg_add_timestamp (struct nn_xmsg *m, nn_wctime_t t);

File diff suppressed because it is too large Load diff

View file

@ -213,7 +213,7 @@ int spdp_write (struct participant *pp)
terribly important, the msg will grow as needed, address space is terribly important, the msg will grow as needed, address space is
essentially meaningless because we only use the message to essentially meaningless because we only use the message to
construct the payload. */ construct the payload. */
mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid.prefix, 0, NN_XMSG_KIND_DATA); mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, NULL, 0, NN_XMSG_KIND_DATA);
nn_plist_init_empty (&ps); nn_plist_init_empty (&ps);
ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET | ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET |
@ -343,7 +343,7 @@ static int spdp_dispose_unregister_with_wr (struct participant *pp, unsigned ent
return 0; return 0;
} }
mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid.prefix, 0, NN_XMSG_KIND_DATA); mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, NULL, 0, NN_XMSG_KIND_DATA);
nn_plist_init_empty (&ps); nn_plist_init_empty (&ps);
ps.present |= PP_PARTICIPANT_GUID; ps.present |= PP_PARTICIPANT_GUID;
ps.participant_guid = pp->e.guid; ps.participant_guid = pp->e.guid;
@ -437,7 +437,7 @@ static int handle_SPDP_dead (const struct receiver_state *rst, ddsi_entityid_t p
guid = datap->participant_guid; guid = datap->participant_guid;
GVLOGDISC (" %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (guid)); GVLOGDISC (" %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (guid));
assert (guid.entityid.u == NN_ENTITYID_PARTICIPANT); assert (guid.entityid.u == NN_ENTITYID_PARTICIPANT);
if (allow_proxy_participant_deletion(gv, &guid, pwr_entityid)) if (is_proxy_participant_deletion_allowed(gv, &guid, pwr_entityid))
{ {
if (delete_proxy_participant_by_guid (gv, &guid, timestamp, 0) < 0) if (delete_proxy_participant_by_guid (gv, &guid, timestamp, 0) < 0)
{ {
@ -999,7 +999,7 @@ static int sedp_write_endpoint
the QoS and other settings. So the header fields aren't really the QoS and other settings. So the header fields aren't really
important, except that they need to be set to reasonable things important, except that they need to be set to reasonable things
or it'll crash */ or it'll crash */
mpayload = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA); mpayload = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, NULL, 0, NN_XMSG_KIND_DATA);
nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0);
if (xqos) nn_xqos_addtomsg (mpayload, xqos, qosdiff); if (xqos) nn_xqos_addtomsg (mpayload, xqos, qosdiff);
nn_xmsg_addpar_sentinel (mpayload); nn_xmsg_addpar_sentinel (mpayload);
@ -1467,7 +1467,7 @@ int sedp_write_topic (struct participant *pp, const struct nn_plist *datap)
sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER);
mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA); mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid, NULL, 0, NN_XMSG_KIND_DATA);
delta = nn_xqos_delta (&datap->qos, &sedp_wr->e.gv->default_xqos_tp, ~(uint64_t)0); delta = nn_xqos_delta (&datap->qos, &sedp_wr->e.gv->default_xqos_tp, ~(uint64_t)0);
if (sedp_wr->e.gv->config.explicitly_publish_qos_set_to_default) if (sedp_wr->e.gv->config.explicitly_publish_qos_set_to_default)
delta |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; delta |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK;
@ -1505,7 +1505,7 @@ int sedp_write_cm_participant (struct participant *pp, int alive)
the QoS and other settings. So the header fields aren't really the QoS and other settings. So the header fields aren't really
important, except that they need to be set to reasonable things important, except that they need to be set to reasonable things
or it'll crash */ or it'll crash */
mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid.prefix, 0, NN_XMSG_KIND_DATA); mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid, NULL, 0, NN_XMSG_KIND_DATA);
nn_plist_init_empty (&ps); nn_plist_init_empty (&ps);
ps.present = PP_PARTICIPANT_GUID; ps.present = PP_PARTICIPANT_GUID;
ps.participant_guid = pp->e.guid; ps.participant_guid = pp->e.guid;

View file

@ -2119,7 +2119,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader
ddsrt_avl_insert_ipath (&pwr_readers_treedef, &pwr->readers, m, &path); ddsrt_avl_insert_ipath (&pwr_readers_treedef, &pwr->readers, m, &path);
local_reader_ary_insert(&pwr->rdary, rd); local_reader_ary_insert(&pwr->rdary, rd);
ddsrt_mutex_unlock (&pwr->e.lock); ddsrt_mutex_unlock (&pwr->e.lock);
qxev_pwr_entityid (pwr, &rd->e.guid.prefix); qxev_pwr_entityid (pwr, &rd->e.guid);
ELOGDISC (pwr, "\n"); ELOGDISC (pwr, "\n");
@ -2163,7 +2163,7 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer
PGUID (wr->e.guid), PGUID (prd->e.guid)); PGUID (wr->e.guid), PGUID (prd->e.guid));
ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path); ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path);
ddsrt_mutex_unlock (&prd->e.lock); ddsrt_mutex_unlock (&prd->e.lock);
qxev_prd_entityid (prd, &wr->e.guid.prefix); qxev_prd_entityid (prd, &wr->e.guid);
} }
} }
@ -3974,6 +3974,8 @@ void new_proxy_participant
nn_xqos_mergein_missing (&proxypp->plist->qos, &gv->default_plist_pp.qos, ~(uint64_t)0); nn_xqos_mergein_missing (&proxypp->plist->qos, &gv->default_plist_pp.qos, ~(uint64_t)0);
ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups); ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups);
set_proxy_participant_security_info(proxypp, plist);
if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS) if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS)
proxypp->kernel_sequence_numbers = 1; proxypp->kernel_sequence_numbers = 1;
else else
@ -4289,6 +4291,11 @@ static void proxy_endpoint_common_init (struct entity_common *e, struct proxy_en
else else
memset (&c->group_guid, 0, sizeof (c->group_guid)); memset (&c->group_guid, 0, sizeof (c->group_guid));
#ifdef DDSI_INCLUDE_SECURITY
c->security_info.security_attributes = 0;
c->security_info.plugin_security_attributes = 0;
#endif
ref_proxy_participant (proxypp, c); ref_proxy_participant (proxypp, c);
} }
@ -4394,6 +4401,8 @@ int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
pwr->ddsi2direct_cb = 0; pwr->ddsi2direct_cb = 0;
pwr->ddsi2direct_cbarg = 0; pwr->ddsi2direct_cbarg = 0;
set_proxy_writer_security_info(pwr, plist);
local_reader_ary_init (&pwr->rdary); local_reader_ary_init (&pwr->rdary);
/* locking the entity prevents matching while the built-in topic hasn't been published yet */ /* locking the entity prevents matching while the built-in topic hasn't been published yet */
@ -4437,7 +4446,7 @@ void update_proxy_writer (struct proxy_writer *pwr, seqno_t seq, struct addrset
rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, &m->rd_guid); rd = ephash_lookup_reader_guid (pwr->e.gv->guid_hash, &m->rd_guid);
if (rd) if (rd)
{ {
qxev_pwr_entityid (pwr, &rd->e.guid.prefix); qxev_pwr_entityid (pwr, &rd->e.guid);
} }
m = ddsrt_avl_iter_next (&iter); m = ddsrt_avl_iter_next (&iter);
} }
@ -4494,7 +4503,7 @@ void update_proxy_reader (struct proxy_reader *prd, seqno_t seq, struct addrset
ddsrt_mutex_lock (&wr->e.lock); ddsrt_mutex_lock (&wr->e.lock);
rebuild_writer_addrset (wr); rebuild_writer_addrset (wr);
ddsrt_mutex_unlock (&wr->e.lock); ddsrt_mutex_unlock (&wr->e.lock);
qxev_prd_entityid (prd, &wr->e.guid.prefix); qxev_prd_entityid (prd, &wr->e.guid);
} }
wrguid = guid_next; wrguid = guid_next;
ddsrt_mutex_lock (&prd->e.lock); ddsrt_mutex_lock (&prd->e.lock);
@ -4582,6 +4591,8 @@ int new_proxy_reader (struct q_globals *gv, const struct ddsi_guid *ppguid, cons
#endif #endif
prd->is_fict_trans_reader = 0; prd->is_fict_trans_reader = 0;
set_proxy_reader_security_info(prd, plist);
ddsrt_avl_init (&prd_writers_treedef, &prd->writers); ddsrt_avl_init (&prd_writers_treedef, &prd->writers);
/* locking the entity prevents matching while the built-in topic hasn't been published yet */ /* locking the entity prevents matching while the built-in topic hasn't been published yet */

View file

@ -53,6 +53,7 @@
#include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/ddsi_mcgroup.h"
#include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_serdata.h"
#include "dds/ddsi/ddsi_serdata_default.h" /* FIXME: get rid of this */ #include "dds/ddsi/ddsi_serdata_default.h" /* FIXME: get rid of this */
#include "dds/ddsi/ddsi_security_omg.h"
#include "dds/ddsi/sysdeps.h" #include "dds/ddsi/sysdeps.h"
#include "dds__whc.h" #include "dds__whc.h"
@ -278,7 +279,34 @@ static void set_sampleinfo_proxy_writer (struct nn_rsample_info *sampleinfo, dds
sampleinfo->pwr = pwr; sampleinfo->pwr = pwr;
} }
static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, Data_t *msg, size_t size, int byteswap, struct nn_rsample_info *sampleinfo, unsigned char **payloadp) static int set_sampleinfo_bswap (struct nn_rsample_info *sampleinfo, struct CDRHeader *hdr)
{
if (hdr)
{
switch (hdr->identifier)
{
case CDR_BE:
case PL_CDR_BE:
{
sampleinfo->bswap = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN) ? 1 : 0;
break;
}
case CDR_LE:
case PL_CDR_LE:
{
sampleinfo->bswap = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN) ? 0 : 1;
break;
}
default:
{
return 0;
}
}
}
return 1;
}
static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, Data_t *msg, size_t size, int byteswap, struct nn_rsample_info *sampleinfo, unsigned char **payloadp, uint32_t *payloadsz)
{ {
/* on success: sampleinfo->{seq,rst,statusinfo,pt_wr_info_zoff,bswap,complex_qos} all set */ /* on success: sampleinfo->{seq,rst,statusinfo,pt_wr_info_zoff,bswap,complex_qos} all set */
ddsi_guid_t pwr_guid; ddsi_guid_t pwr_guid;
@ -354,6 +382,7 @@ static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, D
{ {
/*TRACE (("no payload\n"));*/ /*TRACE (("no payload\n"));*/
*payloadp = NULL; *payloadp = NULL;
*payloadsz = 0;
sampleinfo->size = 0; sampleinfo->size = 0;
} }
else if ((size_t) ((char *) ptr + 4 - (char *) msg) > size) else if ((size_t) ((char *) ptr + 4 - (char *) msg) > size)
@ -363,35 +392,16 @@ static int valid_Data (const struct receiver_state *rst, struct nn_rmsg *rmsg, D
} }
else else
{ {
struct CDRHeader *hdr;
sampleinfo->size = (uint32_t) ((char *) msg + size - (char *) ptr); sampleinfo->size = (uint32_t) ((char *) msg + size - (char *) ptr);
*payloadsz = sampleinfo->size;
*payloadp = ptr; *payloadp = ptr;
hdr = (struct CDRHeader *) ptr;
switch (hdr->identifier)
{
case CDR_BE:
case PL_CDR_BE:
{
sampleinfo->bswap = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? 1 : 0);
break;
}
case CDR_LE:
case PL_CDR_LE:
{
sampleinfo->bswap = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? 0 : 1);
break;
}
default:
return 0;
}
} }
return 1; return 1;
} }
static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rmsg, DataFrag_t *msg, size_t size, int byteswap, struct nn_rsample_info *sampleinfo, unsigned char **payloadp) static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rmsg, DataFrag_t *msg, size_t size, int byteswap, struct nn_rsample_info *sampleinfo, unsigned char **payloadp, uint32_t *payloadsz)
{ {
/* on success: sampleinfo->{rst,statusinfo,pt_wr_info_zoff,bswap,complex_qos} all set */ /* on success: sampleinfo->{rst,statusinfo,pt_wr_info_zoff,bswap,complex_qos} all set */
uint32_t payloadsz;
ddsi_guid_t pwr_guid; ddsi_guid_t pwr_guid;
unsigned char *ptr; unsigned char *ptr;
@ -473,18 +483,17 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms
} }
*payloadp = ptr; *payloadp = ptr;
payloadsz = (uint32_t) ((char *) msg + size - (char *) ptr); *payloadsz = (uint32_t) ((char *) msg + size - (char *) ptr);
if ((uint32_t) msg->fragmentsInSubmessage * msg->fragmentSize <= payloadsz) if ((uint32_t) msg->fragmentsInSubmessage * msg->fragmentSize <= (*payloadsz))
; /* all spec'd fragments fit in payload */ ; /* all spec'd fragments fit in payload */
else if ((uint32_t) (msg->fragmentsInSubmessage - 1) * msg->fragmentSize >= payloadsz) else if ((uint32_t) (msg->fragmentsInSubmessage - 1) * msg->fragmentSize >= (*payloadsz))
return 0; /* I can live with a short final fragment, but _only_ the final one */ return 0; /* I can live with a short final fragment, but _only_ the final one */
else if ((uint32_t) (msg->fragmentStartingNum - 1) * msg->fragmentSize + payloadsz >= msg->sampleSize) else if ((uint32_t) (msg->fragmentStartingNum - 1) * msg->fragmentSize + (*payloadsz) >= msg->sampleSize)
; /* final fragment is long enough to cover rest of sample */ ; /* final fragment is long enough to cover rest of sample */
else else
return 0; return 0;
if (msg->fragmentStartingNum == 1) if (msg->fragmentStartingNum == 1)
{ {
struct CDRHeader *hdr = (struct CDRHeader *) ptr;
if ((size_t) ((char *) ptr + 4 - (char *) msg) > size) if ((size_t) ((char *) ptr + 4 - (char *) msg) > size)
{ {
/* no space for the header -- technically, allowing small /* no space for the header -- technically, allowing small
@ -492,23 +501,6 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms
prefer this */ prefer this */
return 0; return 0;
} }
switch (hdr->identifier)
{
case CDR_BE:
case PL_CDR_BE:
{
sampleinfo->bswap = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? 1 : 0);
break;
}
case CDR_LE:
case PL_CDR_LE:
{
sampleinfo->bswap = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? 0 : 1);
break;
}
default:
return 0;
}
} }
return 1; return 1;
} }
@ -527,6 +519,7 @@ static int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader
gap->gapList.numbits = numbits; gap->gapList.numbits = numbits;
memcpy (gap->bits, bits, NN_SEQUENCE_NUMBER_SET_BITS_SIZE (numbits)); memcpy (gap->bits, bits, NN_SEQUENCE_NUMBER_SET_BITS_SIZE (numbits));
nn_xmsg_submsg_setnext (msg, sm_marker); nn_xmsg_submsg_setnext (msg, sm_marker);
encode_datawriter_submsg(msg, sm_marker, wr);
return 0; return 0;
} }
@ -537,7 +530,7 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state *
ASSERT_MUTEX_HELD (&wr->e.lock); ASSERT_MUTEX_HELD (&wr->e.lock);
assert (wr->reliable); assert (wr->reliable);
m = nn_xmsg_new (wr->e.gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL); m = nn_xmsg_new (wr->e.gv->xmsgpool, &wr->e.guid, wr->c.pp, 0, NN_XMSG_KIND_CONTROL);
if (nn_xmsg_setdstPRD (m, prd) < 0) if (nn_xmsg_setdstPRD (m, prd) < 0)
{ {
/* If we don't have an address, give up immediately */ /* If we don't have an address, give up immediately */
@ -610,7 +603,7 @@ static int accept_ack_or_hb_w_timeout (nn_count_t new_count, nn_count_t *exp_cou
return 1; return 1;
} }
static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const AckNack_t *msg, nn_wctime_t timestamp) static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const AckNack_t *msg, nn_wctime_t timestamp, SubmessageKind_t prev_smid)
{ {
struct proxy_reader *prd; struct proxy_reader *prd;
struct wr_prd_match *rn; struct wr_prd_match *rn;
@ -666,6 +659,12 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
return 1; return 1;
} }
if (!validate_msg_decoding(&(prd->e), &(prd->c), prd->c.proxypp, rst, prev_smid))
{
RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" clear submsg from protected src)", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow); lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow);
@ -934,7 +933,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac
RSTTRACE (" XGAP%"PRId64"..%"PRId64"/%u:", gapstart, gapend, gapnumbits); RSTTRACE (" XGAP%"PRId64"..%"PRId64"/%u:", gapstart, gapend, gapnumbits);
for (uint32_t i = 0; i < gapnumbits; i++) for (uint32_t i = 0; i < gapnumbits; i++)
RSTTRACE ("%c", nn_bitset_isset (gapnumbits, gapbits, i) ? '1' : '0'); RSTTRACE ("%c", nn_bitset_isset (gapnumbits, gapbits, i) ? '1' : '0');
m = nn_xmsg_new (rst->gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL); m = nn_xmsg_new (rst->gv->xmsgpool, &wr->e.guid, wr->c.pp, 0, NN_XMSG_KIND_CONTROL);
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
nn_xmsg_setencoderid (m, wr->partition_id); nn_xmsg_setencoderid (m, wr->partition_id);
#endif #endif
@ -1094,7 +1093,7 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand
} }
} }
static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Heartbeat_t *msg, nn_wctime_t timestamp) static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Heartbeat_t *msg, nn_wctime_t timestamp, SubmessageKind_t prev_smid)
{ {
/* We now cheat: and process the heartbeat for _all_ readers, /* We now cheat: and process the heartbeat for _all_ readers,
always, regardless of the destination address in the Heartbeat always, regardless of the destination address in the Heartbeat
@ -1132,6 +1131,12 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
return 1; return 1;
} }
if (!validate_msg_decoding(&(pwr->e), &(pwr->c), pwr->c.proxypp, rst, prev_smid))
{
RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" clear submsg from protected src)", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, /* liveliness is still only implemented partially (with all set to AUTOMATIC,
BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
@ -1244,7 +1249,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct
return 1; return 1;
} }
static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime_t tnow), const HeartbeatFrag_t *msg) static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime_t tnow), const HeartbeatFrag_t *msg, SubmessageKind_t prev_smid)
{ {
const seqno_t seq = fromSN (msg->writerSN); const seqno_t seq = fromSN (msg->writerSN);
const nn_fragment_number_t fragnum = msg->lastFragmentNum - 1; /* we do 0-based */ const nn_fragment_number_t fragnum = msg->lastFragmentNum - 1; /* we do 0-based */
@ -1269,6 +1274,12 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
return 1; return 1;
} }
if (!validate_msg_decoding(&(pwr->e), &(pwr->c), pwr->c.proxypp, rst, prev_smid))
{
RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" clear submsg from protected src)", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
@ -1355,7 +1366,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime
return 1; return 1;
} }
static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const NackFrag_t *msg) static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const NackFrag_t *msg, SubmessageKind_t prev_smid)
{ {
struct proxy_reader *prd; struct proxy_reader *prd;
struct wr_prd_match *rn; struct wr_prd_match *rn;
@ -1396,6 +1407,12 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
return 1; return 1;
} }
if (!validate_msg_decoding(&(prd->e), &(prd->c), prd->c.proxypp, rst, prev_smid))
{
RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" clear submsg from protected src)", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow); lease_renew (ddsrt_atomic_ldvoidp (&prd->c.proxypp->lease), tnow);
@ -1446,7 +1463,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N
static uint32_t zero = 0; static uint32_t zero = 0;
struct nn_xmsg *m; struct nn_xmsg *m;
RSTTRACE (" msg not available: scheduling Gap\n"); RSTTRACE (" msg not available: scheduling Gap\n");
m = nn_xmsg_new (rst->gv->xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL); m = nn_xmsg_new (rst->gv->xmsgpool, &wr->e.guid, wr->c.pp, 0, NN_XMSG_KIND_CONTROL);
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
nn_xmsg_setencoderid (m, wr->partition_id); nn_xmsg_setencoderid (m, wr->partition_id);
#endif #endif
@ -1590,7 +1607,7 @@ static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, se
return gap_was_valuable; return gap_was_valuable;
} }
static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Gap_t *msg) static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Gap_t *msg, SubmessageKind_t prev_smid)
{ {
/* Option 1: Process the Gap for the proxy writer and all /* Option 1: Process the Gap for the proxy writer and all
out-of-sync readers: what do I care which reader is being out-of-sync readers: what do I care which reader is being
@ -1643,6 +1660,12 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm
return 1; return 1;
} }
if (!validate_msg_decoding(&(pwr->e), &(pwr->c), pwr->c.proxypp, rst, prev_smid))
{
RSTTRACE (" "PGUIDFMT" -> "PGUIDFMT" clear submsg from protected src)", PGUID (src), PGUID (dst));
return 1;
}
/* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */ /* liveliness is still only implemented partially (with all set to AUTOMATIC, BY_PARTICIPANT, &c.), so we simply renew the proxy participant's lease. */
lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow);
@ -2346,7 +2369,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con
} }
} }
static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup, SubmessageKind_t prev_smid)
{ {
RSTTRACE ("DATA("PGUIDFMT" -> "PGUIDFMT" #%"PRId64, RSTTRACE ("DATA("PGUIDFMT" -> "PGUIDFMT" #%"PRId64,
PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u,
@ -2358,6 +2381,15 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r
return 1; return 1;
} }
if (sampleinfo->pwr)
{
if (!validate_msg_decoding(&(sampleinfo->pwr->e), &(sampleinfo->pwr->c), sampleinfo->pwr->c.proxypp, rst, prev_smid))
{
RSTTRACE (" clear submsg from protected src "PGUIDFMT")", PGUID (sampleinfo->pwr->e.guid));
return 1;
}
}
if (sampleinfo->size > rst->gv->config.max_sample_size) if (sampleinfo->size > rst->gv->config.max_sample_size)
drop_oversize (rst, rmsg, &msg->x, sampleinfo); drop_oversize (rst, rmsg, &msg->x, sampleinfo);
else else
@ -2391,7 +2423,7 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r
return 1; return 1;
} }
static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup, SubmessageKind_t prev_smid)
{ {
RSTTRACE ("DATAFRAG("PGUIDFMT" -> "PGUIDFMT" #%"PRId64"/[%u..%u]", RSTTRACE ("DATAFRAG("PGUIDFMT" -> "PGUIDFMT" #%"PRId64"/[%u..%u]",
PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u,
@ -2404,6 +2436,15 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct
return 1; return 1;
} }
if (sampleinfo->pwr)
{
if (!validate_msg_decoding(&(sampleinfo->pwr->e), &(sampleinfo->pwr->c), sampleinfo->pwr->c.proxypp, rst, prev_smid))
{
RSTTRACE (" clear submsg from protected src "PGUIDFMT")", PGUID (sampleinfo->pwr->e.guid));
return 1;
}
}
if (sampleinfo->size > rst->gv->config.max_sample_size) if (sampleinfo->size > rst->gv->config.max_sample_size)
drop_oversize (rst, rmsg, &msg->x, sampleinfo); drop_oversize (rst, rmsg, &msg->x, sampleinfo);
else else
@ -2606,7 +2647,8 @@ static int handle_submsg_sequence
unsigned char * const msg /* NOT const - we may byteswap it */, unsigned char * const msg /* NOT const - we may byteswap it */,
const size_t len, const size_t len,
unsigned char * submsg /* aliases somewhere in msg */, unsigned char * submsg /* aliases somewhere in msg */,
struct nn_rmsg * const rmsg struct nn_rmsg * const rmsg,
bool rtps_encoded /* indicate if the message was rtps encoded */
) )
{ {
const char *state; const char *state;
@ -2618,6 +2660,7 @@ static int handle_submsg_sequence
size_t submsg_size = 0; size_t submsg_size = 0;
unsigned char * end = msg + len; unsigned char * end = msg + len;
struct nn_dqueue *deferred_wakeup = NULL; struct nn_dqueue *deferred_wakeup = NULL;
SubmessageKind_t prev_smid = SMID_PAD;
/* Receiver state is dynamically allocated with lifetime bound to /* Receiver state is dynamically allocated with lifetime bound to
the message. Updates cause a new copy to be created if the the message. Updates cause a new copy to be created if the
@ -2639,6 +2682,7 @@ static int handle_submsg_sequence
false at any time. That's ok: it's real purpose is to filter out false at any time. That's ok: it's real purpose is to filter out
discovery data accidentally sent by Cloud */ discovery data accidentally sent by Cloud */
rst->forme = 1; rst->forme = 1;
rst->rtps_encoded = rtps_encoded;
rst->vendor = hdr->vendorid; rst->vendor = hdr->vendorid;
rst->protocol_version = hdr->version; rst->protocol_version = hdr->version;
rst->srcloc = *srcloc; rst->srcloc = *srcloc;
@ -2700,14 +2744,14 @@ static int handle_submsg_sequence
state = "parse:acknack"; state = "parse:acknack";
if (!valid_AckNack (rst, &sm->acknack, submsg_size, byteswap)) if (!valid_AckNack (rst, &sm->acknack, submsg_size, byteswap))
goto malformed; goto malformed;
handle_AckNack (rst, tnowE, &sm->acknack, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID); handle_AckNack (rst, tnowE, &sm->acknack, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID, prev_smid);
ts_for_latmeas = 0; ts_for_latmeas = 0;
break; break;
case SMID_HEARTBEAT: case SMID_HEARTBEAT:
state = "parse:heartbeat"; state = "parse:heartbeat";
if (!valid_Heartbeat (&sm->heartbeat, submsg_size, byteswap)) if (!valid_Heartbeat (&sm->heartbeat, submsg_size, byteswap))
goto malformed; goto malformed;
handle_Heartbeat (rst, tnowE, rmsg, &sm->heartbeat, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID); handle_Heartbeat (rst, tnowE, rmsg, &sm->heartbeat, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID, prev_smid);
ts_for_latmeas = 0; ts_for_latmeas = 0;
break; break;
case SMID_GAP: case SMID_GAP:
@ -2719,7 +2763,7 @@ static int handle_submsg_sequence
rst after inserting the gap in the admin. */ rst after inserting the gap in the admin. */
if (!valid_Gap (&sm->gap, submsg_size, byteswap)) if (!valid_Gap (&sm->gap, submsg_size, byteswap))
goto malformed; goto malformed;
handle_Gap (rst, tnowE, rmsg, &sm->gap); handle_Gap (rst, tnowE, rmsg, &sm->gap, prev_smid);
ts_for_latmeas = 0; ts_for_latmeas = 0;
break; break;
case SMID_INFO_TS: case SMID_INFO_TS:
@ -2763,27 +2807,37 @@ static int handle_submsg_sequence
state = "parse:nackfrag"; state = "parse:nackfrag";
if (!valid_NackFrag (&sm->nackfrag, submsg_size, byteswap)) if (!valid_NackFrag (&sm->nackfrag, submsg_size, byteswap))
goto malformed; goto malformed;
handle_NackFrag (rst, tnowE, &sm->nackfrag); handle_NackFrag (rst, tnowE, &sm->nackfrag, prev_smid);
ts_for_latmeas = 0; ts_for_latmeas = 0;
break; break;
case SMID_HEARTBEAT_FRAG: case SMID_HEARTBEAT_FRAG:
state = "parse:heartbeatfrag"; state = "parse:heartbeatfrag";
if (!valid_HeartbeatFrag (&sm->heartbeatfrag, submsg_size, byteswap)) if (!valid_HeartbeatFrag (&sm->heartbeatfrag, submsg_size, byteswap))
goto malformed; goto malformed;
handle_HeartbeatFrag (rst, tnowE, &sm->heartbeatfrag); handle_HeartbeatFrag (rst, tnowE, &sm->heartbeatfrag, prev_smid);
ts_for_latmeas = 0; ts_for_latmeas = 0;
break; break;
case SMID_DATA_FRAG: case SMID_DATA_FRAG:
state = "parse:datafrag"; state = "parse:datafrag";
{ {
struct nn_rsample_info sampleinfo; struct nn_rsample_info sampleinfo;
uint32_t datasz = 0;
unsigned char *datap; unsigned char *datap;
size_t submsg_len = submsg_size;
/* valid_DataFrag does not validate the payload */ /* valid_DataFrag does not validate the payload */
if (!valid_DataFrag (rst, rmsg, &sm->datafrag, submsg_size, byteswap, &sampleinfo, &datap)) if (!valid_DataFrag (rst, rmsg, &sm->datafrag, submsg_size, byteswap, &sampleinfo, &datap, &datasz))
goto malformed; goto malformed;
/* This only decodes the payload when needed (possibly reducing the submsg size). */
if (!decode_DataFrag (rst->gv, &sampleinfo, datap, datasz, &submsg_len))
goto malformed;
/* Set the sample bswap according to the payload info (only first fragment has proper header). */
if (sm->datafrag.fragmentStartingNum == 1) {
if (!set_sampleinfo_bswap(&sampleinfo, (struct CDRHeader *)datap))
goto malformed;
}
sampleinfo.timestamp = timestamp; sampleinfo.timestamp = timestamp;
sampleinfo.reception_timestamp = tnowWC; sampleinfo.reception_timestamp = tnowWC;
handle_DataFrag (rst, tnowE, rmsg, &sm->datafrag, submsg_size, &sampleinfo, datap, &deferred_wakeup); handle_DataFrag (rst, tnowE, rmsg, &sm->datafrag, submsg_len, &sampleinfo, datap, &deferred_wakeup, prev_smid);
rst_live = 1; rst_live = 1;
ts_for_latmeas = 0; ts_for_latmeas = 0;
} }
@ -2793,12 +2847,20 @@ static int handle_submsg_sequence
{ {
struct nn_rsample_info sampleinfo; struct nn_rsample_info sampleinfo;
unsigned char *datap; unsigned char *datap;
uint32_t datasz = 0;
size_t submsg_len = submsg_size;
/* valid_Data does not validate the payload */ /* valid_Data does not validate the payload */
if (!valid_Data (rst, rmsg, &sm->data, submsg_size, byteswap, &sampleinfo, &datap)) if (!valid_Data (rst, rmsg, &sm->data, submsg_size, byteswap, &sampleinfo, &datap, &datasz))
goto malformed;
/* This only decodes the payload when needed (possibly reducing the submsg size). */
if (!decode_Data (rst->gv, &sampleinfo, datap, datasz, &submsg_len))
goto malformed;
/* Set the sample bswap according to the payload info. */
if (!set_sampleinfo_bswap(&sampleinfo, (struct CDRHeader *)datap))
goto malformed; goto malformed;
sampleinfo.timestamp = timestamp; sampleinfo.timestamp = timestamp;
sampleinfo.reception_timestamp = tnowWC; sampleinfo.reception_timestamp = tnowWC;
handle_Data (rst, tnowE, rmsg, &sm->data, submsg_size, &sampleinfo, datap, &deferred_wakeup); handle_Data (rst, tnowE, rmsg, &sm->data, submsg_len, &sampleinfo, datap, &deferred_wakeup, prev_smid);
rst_live = 1; rst_live = 1;
ts_for_latmeas = 0; ts_for_latmeas = 0;
} }
@ -2819,6 +2881,38 @@ static int handle_submsg_sequence
GVTRACE ("ENTITY_ID"); GVTRACE ("ENTITY_ID");
break; break;
} }
case SMID_SEC_PREFIX:
state = "parse:sec_prefix";
{
GVTRACE ("SEC_PREFIX");
if (decode_SecPrefix(rst, submsg, submsg_size, end, &rst->src_guid_prefix, &rst->dst_guid_prefix, byteswap) < 0)
goto malformed;
}
break;
case SMID_SEC_BODY:
{
/* Ignore: because it should have been handled by SMID_SEC_PREFIX. */
GVTRACE ("SEC_BODY");
}
break;
case SMID_SEC_POSTFIX:
{
/* Ignore: because it should have been handled by SMID_SEC_PREFIX. */
GVTRACE ("SEC_POSTFIX");
}
break;
case SMID_SRTPS_PREFIX:
{
/* Ignore: it should already have been handled. */
GVTRACE ("SRTPS_PREFIX");
}
break;
case SMID_SRTPS_POSTFIX:
{
/* Ignore: it should already have been handled. */
GVTRACE ("SRTPS_POSTFIX");
}
break;
default: default:
state = "parse:undefined"; state = "parse:undefined";
GVTRACE ("UNDEFINED(%x)", sm->smhdr.submessageId); GVTRACE ("UNDEFINED(%x)", sm->smhdr.submessageId);
@ -2849,6 +2943,7 @@ static int handle_submsg_sequence
ts_for_latmeas = 0; ts_for_latmeas = 0;
break; break;
} }
prev_smid = state_smkind;
submsg += submsg_size; submsg += submsg_size;
GVTRACE ("\n"); GVTRACE ("\n");
} }
@ -2985,8 +3080,36 @@ static bool do_packet (struct thread_state1 * const ts1, struct q_globals *gv, d
GVTRACE ("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu from %s\n", GVTRACE ("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu from %s\n",
PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr); PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr);
} }
nn_rtps_msg_state_t res = decode_rtps_message(ts1,
gv,
&rmsg,
&hdr,
&buff,
&sz,
rbpool,
conn->m_stream);
handle_submsg_sequence (ts1, gv, conn, &srcloc, now (), now_et (), &hdr->guid_prefix, guidprefix, buff, (size_t) sz, buff + RTPS_MESSAGE_HEADER_SIZE, rmsg); if (res != NN_RTPS_MSG_STATE_ERROR)
{
handle_submsg_sequence (ts1,
gv,
conn,
&srcloc,
now (),
now_et (),
&hdr->guid_prefix,
guidprefix,
buff,
(size_t) sz,
buff + RTPS_MESSAGE_HEADER_SIZE,
rmsg,
res == NN_RTPS_MSG_STATE_ENCODED);
}
else
{
/* drop message */
sz = 1;
}
} }
} }
nn_rmsg_commit (rmsg); nn_rmsg_commit (rmsg);

View file

@ -34,6 +34,7 @@
#include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_tkmap.h"
#include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_serdata.h"
#include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_sertopic.h"
#include "dds/ddsi/ddsi_security_omg.h"
#include "dds/ddsi/sysdeps.h" #include "dds/ddsi/sysdeps.h"
#include "dds__whc.h" #include "dds__whc.h"
@ -140,7 +141,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru
assert (wr->reliable); assert (wr->reliable);
assert (hbansreq >= 0); assert (hbansreq >= 0);
if ((msg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTS_t) + sizeof (Heartbeat_t), NN_XMSG_KIND_CONTROL)) == NULL) if ((msg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, wr->c.pp, sizeof (InfoTS_t) + sizeof (Heartbeat_t), NN_XMSG_KIND_CONTROL)) == NULL)
/* out of memory at worst slows down traffic */ /* out of memory at worst slows down traffic */
return NULL; return NULL;
@ -218,6 +219,13 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru
add_Heartbeat (msg, wr, whcst, hbansreq, prd_guid->entityid, issync); add_Heartbeat (msg, wr, whcst, hbansreq, prd_guid->entityid, issync);
} }
/* It is possible that the encoding removed the submessage(s). */
if (nn_xmsg_size(msg) == 0)
{
nn_xmsg_free (msg);
msg = NULL;
}
writer_hbcontrol_note_hb (wr, tnow, hbansreq); writer_hbcontrol_note_hb (wr, tnow, hbansreq);
return msg; return msg;
} }
@ -379,6 +387,7 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta
hb->count = ++wr->hbcount; hb->count = ++wr->hbcount;
nn_xmsg_submsg_setnext (msg, sm_marker); nn_xmsg_submsg_setnext (msg, sm_marker);
encode_datawriter_submsg(msg, sm_marker, wr);
} }
static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t seq, struct ddsi_serdata *serdata, struct nn_xmsg **pmsg) static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t seq, struct ddsi_serdata *serdata, struct nn_xmsg **pmsg)
@ -411,7 +420,7 @@ static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t s
ASSERT_MUTEX_HELD (&wr->e.lock); ASSERT_MUTEX_HELD (&wr->e.lock);
/* INFO_TS: 12 bytes, Data_t: 24 bytes, expected inline QoS: 32 => should be single chunk */ /* INFO_TS: 12 bytes, Data_t: 24 bytes, expected inline QoS: 32 => should be single chunk */
if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL) if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, wr->c.pp, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL)
return DDS_RETCODE_OUT_OF_RESOURCES; return DDS_RETCODE_OUT_OF_RESOURCES;
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
@ -448,9 +457,9 @@ static dds_return_t create_fragment_message_simple (struct writer *wr, seqno_t s
#if TEST_KEYHASH #if TEST_KEYHASH
if (serdata->kind != SDK_KEY || !wr->include_keyhash) if (serdata->kind != SDK_KEY || !wr->include_keyhash)
nn_xmsg_serdata (*pmsg, serdata, 0, ddsi_serdata_size (serdata)); nn_xmsg_serdata (*pmsg, serdata, 0, ddsi_serdata_size (serdata), wr);
#else #else
nn_xmsg_serdata (*pmsg, serdata, 0, ddsi_serdata_size (serdata)); nn_xmsg_serdata (*pmsg, serdata, 0, ddsi_serdata_size (serdata), wr);
#endif #endif
nn_xmsg_submsg_setnext (*pmsg, sm_marker); nn_xmsg_submsg_setnext (*pmsg, sm_marker);
return 0; return 0;
@ -497,7 +506,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru
fragging = (gv->config.fragment_size < size); fragging = (gv->config.fragment_size < size);
/* INFO_TS: 12 bytes, DataFrag_t: 36 bytes, expected inline QoS: 32 => should be single chunk */ /* INFO_TS: 12 bytes, DataFrag_t: 36 bytes, expected inline QoS: 32 => should be single chunk */
if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL) if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, wr->c.pp, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL)
return DDS_RETCODE_OUT_OF_RESOURCES; return DDS_RETCODE_OUT_OF_RESOURCES;
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
@ -618,7 +627,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru
} }
} }
nn_xmsg_serdata (*pmsg, serdata, fragstart, fraglen); nn_xmsg_serdata (*pmsg, serdata, fragstart, fraglen, wr);
nn_xmsg_submsg_setnext (*pmsg, sm_marker); nn_xmsg_submsg_setnext (*pmsg, sm_marker);
#if 0 #if 0
GVTRACE ("queue data%s "PGUIDFMT" #%lld/%u[%u..%u)\n", GVTRACE ("queue data%s "PGUIDFMT" #%lld/%u[%u..%u)\n",
@ -626,6 +635,15 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru
seq, fragnum+1, fragstart, fragstart + fraglen); seq, fragnum+1, fragstart, fragstart + fraglen);
#endif #endif
encode_datawriter_submsg(*pmsg, sm_marker, wr);
/* It is possible that the encoding removed the submessage.
* If there is no content, free the message. */
if (nn_xmsg_size(*pmsg) == 0) {
nn_xmsg_free (*pmsg);
*pmsg = NULL;
}
return ret; return ret;
} }
@ -635,7 +653,7 @@ static void create_HeartbeatFrag (struct writer *wr, seqno_t seq, unsigned fragn
struct nn_xmsg_marker sm_marker; struct nn_xmsg_marker sm_marker;
HeartbeatFrag_t *hbf; HeartbeatFrag_t *hbf;
ASSERT_MUTEX_HELD (&wr->e.lock); ASSERT_MUTEX_HELD (&wr->e.lock);
if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid.prefix, sizeof (HeartbeatFrag_t), NN_XMSG_KIND_CONTROL)) == NULL) if ((*pmsg = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, wr->c.pp, sizeof (HeartbeatFrag_t), NN_XMSG_KIND_CONTROL)) == NULL)
return; /* ignore out-of-memory: HeartbeatFrag is only advisory anyway */ return; /* ignore out-of-memory: HeartbeatFrag is only advisory anyway */
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
nn_xmsg_setencoderid (*pmsg, wr->partition_id); nn_xmsg_setencoderid (*pmsg, wr->partition_id);
@ -664,6 +682,15 @@ static void create_HeartbeatFrag (struct writer *wr, seqno_t seq, unsigned fragn
hbf->count = ++wr->hbfragcount; hbf->count = ++wr->hbfragcount;
nn_xmsg_submsg_setnext (*pmsg, sm_marker); nn_xmsg_submsg_setnext (*pmsg, sm_marker);
encode_datawriter_submsg(*pmsg, sm_marker, wr);
/* It is possible that the encoding removed the submessage.
* If there is no content, free the message. */
if (nn_xmsg_size(*pmsg) == 0)
{
nn_xmsg_free(*pmsg);
*pmsg = NULL;
}
} }
#if 0 #if 0

View file

@ -39,6 +39,7 @@
#include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_xmsg.h"
#include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_serdata.h"
#include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/ddsi_serdata_default.h"
#include "dds/ddsi/ddsi_security_omg.h"
#include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_tkmap.h"
#include "dds__whc.h" #include "dds__whc.h"
@ -182,7 +183,7 @@ static void trace_msg (struct xeventq *evq, const char *func, const struct nn_xm
{ {
if (dds_get_log_mask() & DDS_LC_TRACE) if (dds_get_log_mask() & DDS_LC_TRACE)
{ {
nn_guid_t wrguid; ddsi_guid_t wrguid;
seqno_t wrseq; seqno_t wrseq;
nn_fragment_number_t wrfragid; nn_fragment_number_t wrfragid;
nn_xmsg_guid_seq_fragid (m, &wrguid, &wrseq, &wrfragid); nn_xmsg_guid_seq_fragid (m, &wrguid, &wrseq, &wrfragid);
@ -805,6 +806,9 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
base, an->readerSNState.numbits); base, an->readerSNState.numbits);
for (uint32_t ui = 0; ui != an->readerSNState.numbits; ui++) for (uint32_t ui = 0; ui != an->readerSNState.numbits; ui++)
ETRACE (pwr, "%c", nn_bitset_isset (numbits, an->bits, ui) ? '1' : '0'); ETRACE (pwr, "%c", nn_bitset_isset (numbits, an->bits, ui) ? '1' : '0');
/* Encode the sub-message when needed. */
encode_datareader_submsg(msg, sm_marker, pwr, &rwn->rd_guid);
} }
if (nackfrag_numbits > 0) if (nackfrag_numbits > 0)
@ -835,12 +839,15 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p
for (uint32_t ui = 0; ui != nf->fragmentNumberState.numbits; ui++) for (uint32_t ui = 0; ui != nf->fragmentNumberState.numbits; ui++)
ETRACE (pwr, "%c", nn_bitset_isset (nf->fragmentNumberState.numbits, nf->bits, ui) ? '1' : '0'); ETRACE (pwr, "%c", nn_bitset_isset (nf->fragmentNumberState.numbits, nf->bits, ui) ? '1' : '0');
} }
/* Encode the sub-message when needed. */
encode_datareader_submsg(msg, sm_marker, pwr, &rwn->rd_guid);
} }
ETRACE (pwr, "\n"); ETRACE (pwr, "\n");
} }
static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, nn_mtime_t tnow) static void handle_xevk_acknack (struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow)
{ {
/* FIXME: ought to keep track of which NACKs are being generated in /* FIXME: ought to keep track of which NACKs are being generated in
response to a Heartbeat. There is no point in having multiple response to a Heartbeat. There is no point in having multiple
@ -872,9 +879,18 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent
if (addrset_any_uc (pwr->c.as, &loc) || addrset_any_mc (pwr->c.as, &loc)) if (addrset_any_uc (pwr->c.as, &loc) || addrset_any_mc (pwr->c.as, &loc))
{ {
seqno_t nack_seq; seqno_t nack_seq;
if ((msg = nn_xmsg_new (gv->xmsgpool, &ev->u.acknack.rd_guid.prefix, ACKNACK_SIZE_MAX, NN_XMSG_KIND_CONTROL)) == NULL)
struct participant *pp = NULL;
if (q_omg_security_enabled())
{
struct reader *rd = ephash_lookup_reader_guid(pwr->e.gv->guid_hash, &ev->u.acknack.rd_guid);
if (rd)
pp = rd->c.pp;
}
if ((msg = nn_xmsg_new (gv->xmsgpool, &ev->u.acknack.rd_guid, pp, ACKNACK_SIZE_MAX, NN_XMSG_KIND_CONTROL)) == NULL)
goto outofmem; goto outofmem;
nn_xmsg_setdst1 (msg, &ev->u.acknack.pwr_guid.prefix, &loc); nn_xmsg_setdst1 (gv, msg, &ev->u.acknack.pwr_guid.prefix, &loc);
if (gv->config.meas_hb_to_ack_latency && rwn->hb_timestamp.v) if (gv->config.meas_hb_to_ack_latency && rwn->hb_timestamp.v)
{ {
/* If HB->ACK latency measurement is enabled, and we have a /* If HB->ACK latency measurement is enabled, and we have a
@ -886,7 +902,13 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent
rwn->hb_timestamp.v = 0; rwn->hb_timestamp.v = 0;
} }
add_AckNack (msg, pwr, rwn, &nack_seq); add_AckNack (msg, pwr, rwn, &nack_seq);
if (nack_seq) if (nn_xmsg_size(msg) == 0)
{
/* No AckNack added. */
nn_xmsg_free(msg);
msg = NULL;
}
else if (nack_seq)
{ {
rwn->t_last_nack = tnow; rwn->t_last_nack = tnow;
rwn->seq_last_nack = nack_seq; rwn->seq_last_nack = nack_seq;
@ -948,7 +970,7 @@ static bool resend_spdp_sample_by_guid_key (struct writer *wr, const ddsi_guid_t
nn_plist_init_empty (&ps); nn_plist_init_empty (&ps);
ps.present |= PP_PARTICIPANT_GUID; ps.present |= PP_PARTICIPANT_GUID;
ps.participant_guid = *guid; ps.participant_guid = *guid;
struct nn_xmsg *mpayload = nn_xmsg_new (gv->xmsgpool, &guid->prefix, 0, NN_XMSG_KIND_DATA); struct nn_xmsg *mpayload = nn_xmsg_new (gv->xmsgpool, guid, wr->c.pp, 0, NN_XMSG_KIND_DATA);
nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); nn_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0);
nn_xmsg_addpar_sentinel (mpayload); nn_xmsg_addpar_sentinel (mpayload);
nn_plist_fini (&ps); nn_plist_fini (&ps);
@ -1387,7 +1409,7 @@ void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg)
ddsrt_mutex_unlock (&evq->lock); ddsrt_mutex_unlock (&evq->lock);
} }
void qxev_prd_entityid (struct proxy_reader *prd, ddsi_guid_prefix_t *id) void qxev_prd_entityid (struct proxy_reader *prd, const ddsi_guid_t *guid)
{ {
struct q_globals * const gv = prd->e.gv; struct q_globals * const gv = prd->e.gv;
struct nn_xmsg *msg; struct nn_xmsg *msg;
@ -1397,10 +1419,10 @@ void qxev_prd_entityid (struct proxy_reader *prd, ddsi_guid_prefix_t *id)
if (! gv->xevents->tev_conn->m_connless) if (! gv->xevents->tev_conn->m_connless)
{ {
msg = nn_xmsg_new (gv->xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL); msg = nn_xmsg_new (gv->xmsgpool, guid, NULL, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL);
if (nn_xmsg_setdstPRD (msg, prd) == 0) if (nn_xmsg_setdstPRD (msg, prd) == 0)
{ {
GVTRACE (" qxev_prd_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id)); GVTRACE (" qxev_prd_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (guid->prefix));
nn_xmsg_add_entityid (msg); nn_xmsg_add_entityid (msg);
ddsrt_mutex_lock (&gv->xevents->lock); ddsrt_mutex_lock (&gv->xevents->lock);
ev = qxev_common_nt (gv->xevents, XEVK_ENTITYID); ev = qxev_common_nt (gv->xevents, XEVK_ENTITYID);
@ -1415,7 +1437,7 @@ void qxev_prd_entityid (struct proxy_reader *prd, ddsi_guid_prefix_t *id)
} }
} }
void qxev_pwr_entityid (struct proxy_writer *pwr, ddsi_guid_prefix_t *id) void qxev_pwr_entityid (struct proxy_writer *pwr, const ddsi_guid_t *guid)
{ {
struct q_globals * const gv = pwr->e.gv; struct q_globals * const gv = pwr->e.gv;
struct nn_xmsg *msg; struct nn_xmsg *msg;
@ -1425,10 +1447,10 @@ void qxev_pwr_entityid (struct proxy_writer *pwr, ddsi_guid_prefix_t *id)
if (! pwr->evq->tev_conn->m_connless) if (! pwr->evq->tev_conn->m_connless)
{ {
msg = nn_xmsg_new (gv->xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL); msg = nn_xmsg_new (gv->xmsgpool, guid, NULL, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL);
if (nn_xmsg_setdstPWR (msg, pwr) == 0) if (nn_xmsg_setdstPWR (msg, pwr) == 0)
{ {
GVTRACE (" qxev_pwr_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id)); GVTRACE (" qxev_pwr_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (guid->prefix));
nn_xmsg_add_entityid (msg); nn_xmsg_add_entityid (msg);
ddsrt_mutex_lock (&pwr->evq->lock); ddsrt_mutex_lock (&pwr->evq->lock);
ev = qxev_common_nt (pwr->evq, XEVK_ENTITYID); ev = qxev_common_nt (pwr->evq, XEVK_ENTITYID);

View file

@ -41,6 +41,7 @@
#include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_ephash.h"
#include "dds/ddsi/q_freelist.h" #include "dds/ddsi/q_freelist.h"
#include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/ddsi_serdata_default.h"
#include "dds/ddsi/ddsi_security_omg.h"
#define NN_XMSG_MAX_ALIGN 8 #define NN_XMSG_MAX_ALIGN 8
#define NN_XMSG_CHUNK_SIZE 128 #define NN_XMSG_CHUNK_SIZE 128
@ -72,6 +73,11 @@ struct nn_xmsg {
int have_params; int have_params;
struct ddsi_serdata *refd_payload; struct ddsi_serdata *refd_payload;
ddsrt_iovec_t refd_payload_iov; ddsrt_iovec_t refd_payload_iov;
#ifdef DDSI_INCLUDE_SECURITY
/* Used as pointer to contain encoded payload to which iov can alias. */
unsigned char *refd_payload_encoded;
nn_msg_sec_info_t sec_info;
#endif
int64_t maxdelay; int64_t maxdelay;
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
uint32_t encoderid; uint32_t encoderid;
@ -223,6 +229,9 @@ struct nn_xpack
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
uint32_t encoderId; uint32_t encoderId;
#endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */
#ifdef DDSI_INCLUDE_SECURITY
nn_msg_sec_info_t sec_info;
#endif
}; };
static size_t align4u (size_t x) static size_t align4u (size_t x)
@ -283,6 +292,12 @@ static void nn_xmsg_reinit (struct nn_xmsg *m, enum nn_xmsg_kind kind)
m->dstmode = NN_XMSG_DST_UNSET; m->dstmode = NN_XMSG_DST_UNSET;
m->kind = kind; m->kind = kind;
m->maxdelay = 0; m->maxdelay = 0;
#ifdef DDSI_INCLUDE_SECURITY
m->refd_payload_encoded = NULL;
m->sec_info.use_rtps_encoding = 0;
m->sec_info.src_pp_handle = 0;
m->sec_info.dst_pp_handle = 0;
#endif
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
m->encoderid = 0; m->encoderid = 0;
#endif #endif
@ -322,14 +337,29 @@ static struct nn_xmsg *nn_xmsg_allocnew (struct nn_xmsgpool *pool, size_t expect
return m; return m;
} }
struct nn_xmsg *nn_xmsg_new (struct nn_xmsgpool *pool, const ddsi_guid_prefix_t *src_guid_prefix, size_t expected_size, enum nn_xmsg_kind kind) struct nn_xmsg *nn_xmsg_new (struct nn_xmsgpool *pool, const ddsi_guid_t *src_guid, struct participant *pp, size_t expected_size, enum nn_xmsg_kind kind)
{ {
struct nn_xmsg *m; struct nn_xmsg *m;
if ((m = nn_freelist_pop (&pool->freelist)) != NULL) if ((m = nn_freelist_pop (&pool->freelist)) != NULL)
nn_xmsg_reinit (m, kind); nn_xmsg_reinit (m, kind);
else if ((m = nn_xmsg_allocnew (pool, expected_size, kind)) == NULL) else if ((m = nn_xmsg_allocnew (pool, expected_size, kind)) == NULL)
return NULL; return NULL;
m->data->src.guid_prefix = nn_hton_guid_prefix (*src_guid_prefix); m->data->src.guid_prefix = nn_hton_guid_prefix (src_guid->prefix);
#ifdef DDSI_INCLUDE_SECURITY
m->sec_info.use_rtps_encoding = 0;
if (pp && q_omg_participant_is_secure(pp))
{
if (q_omg_security_is_local_rtps_protected(pp, src_guid->entityid))
{
m->sec_info.use_rtps_encoding = 1;
m->sec_info.src_pp_handle = q_omg_security_get_local_participant_handle(pp);
}
}
#else
DDSRT_UNUSED_ARG(pp);
#endif
return m; return m;
} }
@ -344,6 +374,9 @@ void nn_xmsg_free (struct nn_xmsg *m)
struct nn_xmsgpool *pool = m->pool; struct nn_xmsgpool *pool = m->pool;
if (m->refd_payload) if (m->refd_payload)
ddsi_serdata_to_ser_unref (m->refd_payload, &m->refd_payload_iov); ddsi_serdata_to_ser_unref (m->refd_payload, &m->refd_payload_iov);
#ifdef DDSI_INCLUDE_SECURITY
ddsrt_free(m->refd_payload_encoded);
#endif
if (m->dstmode == NN_XMSG_DST_ALL) if (m->dstmode == NN_XMSG_DST_ALL)
{ {
unref_addrset (m->dstaddr.all.as); unref_addrset (m->dstaddr.all.as);
@ -385,6 +418,13 @@ static int submsg_is_compatible (const struct nn_xmsg *msg, SubmessageKind_t smk
case SMID_DATA: case SMID_DATA_FRAG: case SMID_DATA: case SMID_DATA_FRAG:
/* but data is strictly verboten */ /* but data is strictly verboten */
return 0; return 0;
case SMID_SEC_BODY:
case SMID_SEC_PREFIX:
case SMID_SEC_POSTFIX:
case SMID_SRTPS_PREFIX:
case SMID_SRTPS_POSTFIX:
/* and the security sm are basically data. */
return 0;
} }
assert (0); assert (0);
break; break;
@ -406,6 +446,13 @@ static int submsg_is_compatible (const struct nn_xmsg *msg, SubmessageKind_t smk
won't work for initial transmits, but those currently won't work for initial transmits, but those currently
don't allow a readerId */ don't allow a readerId */
return msg->kindspecific.data.readerId_off == 0; return msg->kindspecific.data.readerId_off == 0;
case SMID_SEC_BODY:
case SMID_SEC_PREFIX:
case SMID_SEC_POSTFIX:
case SMID_SRTPS_PREFIX:
case SMID_SRTPS_POSTFIX:
/* Just do the same as 'normal' data sm. */
return msg->kindspecific.data.readerId_off == 0;
case SMID_ACKNACK: case SMID_ACKNACK:
case SMID_HEARTBEAT: case SMID_HEARTBEAT:
case SMID_GAP: case SMID_GAP:
@ -494,6 +541,80 @@ void nn_xmsg_submsg_setnext (struct nn_xmsg *msg, struct nn_xmsg_marker marker)
((unsigned)(msg->data->payload + msg->sz + plsize - (char *) hdr) - RTPS_SUBMESSAGE_HEADER_SIZE); ((unsigned)(msg->data->payload + msg->sz + plsize - (char *) hdr) - RTPS_SUBMESSAGE_HEADER_SIZE);
} }
#ifdef DDSI_INCLUDE_SECURITY
size_t nn_xmsg_submsg_size (struct nn_xmsg *msg, struct nn_xmsg_marker marker)
{
SubmessageHeader_t *hdr = (SubmessageHeader_t*)nn_xmsg_submsg_from_marker(msg, marker);
return align4u(hdr->octetsToNextHeader + sizeof(SubmessageHeader_t));
}
void nn_xmsg_submsg_remove(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker)
{
/* Just reset the message size to the start of the current sub-message. */
msg->sz = sm_marker.offset;
}
void nn_xmsg_submsg_replace(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker, unsigned char *new_submsg, size_t new_len)
{
/* Size of current sub-message. */
size_t old_len = msg->sz - sm_marker.offset;
/* Adjust the message size to the new sub-message. */
if (old_len < new_len)
{
nn_xmsg_append(msg, NULL, new_len - old_len);
}
else if (old_len > new_len)
{
nn_xmsg_shrink(msg, sm_marker, new_len);
}
/* Just a sanity check: assert(msg_end == submsg_end) */
assert((msg->data->payload + msg->sz) == (msg->data->payload + sm_marker.offset + new_len));
/* Replace the sub-message. */
memcpy(msg->data->payload + sm_marker.offset, new_submsg, new_len);
}
void nn_xmsg_submsg_append_refd_payload(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker)
{
DDSRT_UNUSED_ARG(sm_marker);
/*
* Normally, the refd payload pointer is moved around until it is added to
* the iov of the socket. This reduces the amount of allocations and copies.
*
* However, in a few cases (like security), the sub-message should be one
* complete blob.
* Appending the payload will just do that.
*/
if (msg->refd_payload)
{
void *dst;
/* Get payload information. */
char *payload_ptr = msg->refd_payload_iov.iov_base;
size_t payload_len = msg->refd_payload_iov.iov_len;
/* Make space for the payload (dst points to the start of the appended space). */
dst = nn_xmsg_append(msg, NULL, payload_len);
/* Copy the payload into the submessage. */
memcpy(dst, payload_ptr, payload_len);
/* No need to remember the payload now. */
ddsi_serdata_unref(msg->refd_payload);
msg->refd_payload = NULL;
if (msg->refd_payload_encoded)
{
ddsrt_free(msg->refd_payload_encoded);
msg->refd_payload_encoded = NULL;
}
}
}
#endif /* DDSI_INCLUDE_SECURITY */
void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker marker) void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker marker)
{ {
return msg->data->payload + marker.offset; return msg->data->payload + marker.offset;
@ -560,22 +681,66 @@ void nn_xmsg_add_entityid (struct nn_xmsg * m)
nn_xmsg_submsg_setnext (m, sm); nn_xmsg_submsg_setnext (m, sm);
} }
void nn_xmsg_serdata (struct nn_xmsg *m, struct ddsi_serdata *serdata, size_t off, size_t len) void nn_xmsg_serdata (struct nn_xmsg *m, struct ddsi_serdata *serdata, size_t off, size_t len, struct writer *wr)
{ {
if (serdata->kind != SDK_EMPTY) if (serdata->kind != SDK_EMPTY)
{ {
size_t len4 = align4u (len); size_t len4 = align4u (len);
assert (m->refd_payload == NULL); assert (m->refd_payload == NULL);
m->refd_payload = ddsi_serdata_to_ser_ref (serdata, off, len4, &m->refd_payload_iov); m->refd_payload = ddsi_serdata_to_ser_ref (serdata, off, len4, &m->refd_payload_iov);
#ifdef DDSI_INCLUDE_SECURITY
assert (m->refd_payload_encoded == NULL);
/* When encoding is necessary, m->refd_payload_encoded will be allocated
* and m->refd_payload_iov contents will change to point to that buffer.
* If no encoding is necessary, nothing changes. */
if (!encode_payload(wr, &(m->refd_payload_iov), &(m->refd_payload_encoded)))
{
DDS_CWARNING (&wr->e.gv->logconfig, "nn_xmsg_serdata: failed to encrypt data for "PGUIDFMT"", PGUID (wr->e.guid));
ddsi_serdata_to_ser_unref (m->refd_payload, &m->refd_payload_iov);
assert (m->refd_payload_encoded == NULL);
m->refd_payload_iov.iov_base = NULL;
m->refd_payload_iov.iov_len = 0;
m->refd_payload = NULL;
}
#else
DDSRT_UNUSED_ARG(wr);
#endif
} }
} }
void nn_xmsg_setdst1 (struct nn_xmsg *m, const ddsi_guid_prefix_t *gp, const nn_locator_t *loc) void nn_xmsg_setdst1 (struct q_globals *gv, struct nn_xmsg *m, const ddsi_guid_prefix_t *gp, const nn_locator_t *loc)
{ {
assert (m->dstmode == NN_XMSG_DST_UNSET); assert (m->dstmode == NN_XMSG_DST_UNSET);
m->dstmode = NN_XMSG_DST_ONE; m->dstmode = NN_XMSG_DST_ONE;
m->dstaddr.one.loc = *loc; m->dstaddr.one.loc = *loc;
m->data->dst.guid_prefix = nn_hton_guid_prefix (*gp); m->data->dst.guid_prefix = nn_hton_guid_prefix (*gp);
#ifdef DDSI_INCLUDE_SECURITY
if (m->sec_info.use_rtps_encoding && !m->sec_info.dst_pp_handle)
{
struct proxy_participant *proxypp;
ddsi_guid_t guid;
guid.prefix = *gp;
guid.entityid.u = NN_ENTITYID_PARTICIPANT;
proxypp = ephash_lookup_proxy_participant_guid(gv->guid_hash, &guid);
if (proxypp)
m->sec_info.dst_pp_handle = q_omg_security_get_remote_participant_handle(proxypp);
}
#else
DDSRT_UNUSED_ARG(gv);
#endif
}
bool nn_xmsg_getdst1prefix (struct nn_xmsg *m, ddsi_guid_prefix_t *gp)
{
if (m->dstmode == NN_XMSG_DST_ONE)
{
*gp = nn_hton_guid_prefix(m->data->dst.guid_prefix);
return true;
}
return false;
} }
dds_return_t nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd) dds_return_t nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd)
@ -583,7 +748,7 @@ dds_return_t nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *pr
nn_locator_t loc; nn_locator_t loc;
if (addrset_any_uc (prd->c.as, &loc) || addrset_any_mc (prd->c.as, &loc)) if (addrset_any_uc (prd->c.as, &loc) || addrset_any_mc (prd->c.as, &loc))
{ {
nn_xmsg_setdst1 (m, &prd->e.guid.prefix, &loc); nn_xmsg_setdst1 (prd->e.gv, m, &prd->e.guid.prefix, &loc);
return 0; return 0;
} }
else else
@ -598,7 +763,7 @@ dds_return_t nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pw
nn_locator_t loc; nn_locator_t loc;
if (addrset_any_uc (pwr->c.as, &loc) || addrset_any_mc (pwr->c.as, &loc)) if (addrset_any_uc (pwr->c.as, &loc) || addrset_any_mc (pwr->c.as, &loc))
{ {
nn_xmsg_setdst1 (m, &pwr->e.guid.prefix, &loc); nn_xmsg_setdst1 (pwr->e.gv, m, &pwr->e.guid.prefix, &loc);
return 0; return 0;
} }
DDS_CWARNING (&pwr->e.gv->logconfig, "nn_xmsg_setdstPRD: no address for "PGUIDFMT, PGUID (pwr->e.guid)); DDS_CWARNING (&pwr->e.gv->logconfig, "nn_xmsg_setdstPRD: no address for "PGUIDFMT, PGUID (pwr->e.guid));
@ -953,6 +1118,9 @@ static void nn_xpack_reinit (struct nn_xpack *xp)
xp->msg_len.length = 0; xp->msg_len.length = 0;
xp->included_msgs.latest = NULL; xp->included_msgs.latest = NULL;
xp->maxdelay = T_NEVER; xp->maxdelay = T_NEVER;
#ifdef DDSI_INCLUDE_SECURITY
xp->sec_info.use_rtps_encoding = 0;
#endif
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
xp->encoderId = 0; xp->encoderId = 0;
#endif #endif
@ -1012,6 +1180,34 @@ void nn_xpack_free (struct nn_xpack *xp)
ddsrt_free (xp); ddsrt_free (xp);
} }
static ssize_t nn_xpack_send_rtps(struct nn_xpack * xp, const nn_locator_t *loc)
{
ssize_t ret = -1;
#ifdef DDSI_INCLUDE_SECURITY
/* Only encode when needed. */
if (xp->sec_info.use_rtps_encoding)
{
ret = secure_conn_write(
xp->conn,
loc,
xp->niov,
xp->iov,
xp->call_flags,
&(xp->msg_len),
(xp->dstmode == NN_XMSG_DST_ONE),
&(xp->sec_info),
ddsi_conn_write);
}
else
#endif /* DDSI_INCLUDE_SECURITY */
{
ret = ddsi_conn_write (xp->conn, loc, xp->niov, xp->iov, xp->call_flags);
}
return ret;
}
static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg) static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg)
{ {
struct nn_xpack *xp = varg; struct nn_xpack *xp = varg;
@ -1038,14 +1234,17 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg)
if (!gv->mute) if (!gv->mute)
{ {
nbytes = ddsi_conn_write (xp->conn, loc, xp->niov, xp->iov, xp->call_flags); nbytes = nn_xpack_send_rtps(xp, loc);
#ifndef NDEBUG #ifndef NDEBUG
{ {
size_t i, len; size_t i, len;
for (i = 0, len = 0; i < xp->niov; i++) { for (i = 0, len = 0; i < xp->niov; i++) {
len += xp->iov[i].iov_len; len += xp->iov[i].iov_len;
} }
assert (nbytes == -1 || (size_t) nbytes == len); /* Possible number of bytes written can be larger
* due to security. */
assert (nbytes == -1 || (size_t) nbytes >= len);
} }
#endif #endif
} }
@ -1338,6 +1537,12 @@ static int nn_xpack_mayaddmsg (const struct nn_xpack *xp, const struct nn_xmsg *
return 0; return 0;
#endif #endif
#ifdef DDSI_INCLUDE_SECURITY
/* Don't mix up encoded and plain rtps messages */
if (xp->sec_info.use_rtps_encoding != m->sec_info.use_rtps_encoding)
return 0;
#endif
return addressing_info_eq_onesidederr (xp, m); return addressing_info_eq_onesidederr (xp, m);
} }
@ -1431,6 +1636,9 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag
niov++; niov++;
} }
#ifdef DDSI_INCLUDE_SECURITY
xp->sec_info = m->sec_info;
#endif
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
xp->encoderId = m->encoderid; xp->encoderId = m->encoderid;
#endif #endif