mirror of
https://github.com/open62541/open62541.git
synced 2025-06-03 04:00:21 +00:00
refactor(pubsub): Add explicit Metadata handling to the NetworkMessage encoding
This commit is contained in:
parent
bf0c326911
commit
699d89f834
@ -76,36 +76,22 @@ typedef struct {
|
||||
} UA_DataSetMessageHeader;
|
||||
|
||||
typedef struct {
|
||||
UA_UInt16 fieldCount;
|
||||
UA_DataValue* dataSetFields;
|
||||
UA_ByteString rawFields;
|
||||
/* Json keys for the dataSetFields: TODO: own dataSetMessageType for json? */
|
||||
UA_String* fieldNames;
|
||||
/* This information is for proper en- and decoding needed */
|
||||
UA_DataSetMetaDataType *dataSetMetaDataType;
|
||||
} UA_DataSetMessage_DataKeyFrameData;
|
||||
|
||||
typedef struct {
|
||||
UA_UInt16 fieldIndex;
|
||||
UA_DataValue fieldValue;
|
||||
UA_UInt16 index;
|
||||
UA_DataValue value;
|
||||
} UA_DataSetMessage_DeltaFrameField;
|
||||
|
||||
typedef struct {
|
||||
UA_UInt16 fieldCount;
|
||||
UA_DataSetMessage_DeltaFrameField* deltaFrameFields;
|
||||
} UA_DataSetMessage_DataDeltaFrameData;
|
||||
|
||||
typedef struct {
|
||||
UA_UInt16 dataSetWriterId; /* Goes into the payload header */
|
||||
|
||||
UA_DataSetMessageHeader header;
|
||||
union {
|
||||
UA_DataSetMessage_DataKeyFrameData keyFrameData;
|
||||
UA_DataSetMessage_DataDeltaFrameData deltaFrameData;
|
||||
UA_UInt16 fieldCount;
|
||||
union { /* Array of fields (cf. header->dataSetMessageType) */
|
||||
UA_DataValue *keyFrameFields;
|
||||
UA_DataSetMessage_DeltaFrameField *deltaFrameFields;
|
||||
} data;
|
||||
size_t configuredSize;
|
||||
} UA_DataSetMessage;
|
||||
|
||||
void UA_DataSetMessage_clear(UA_DataSetMessage *p);
|
||||
|
||||
/**
|
||||
* Network Message
|
||||
* ~~~~~~~~~~~~~~~ */
|
||||
@ -188,10 +174,10 @@ typedef struct {
|
||||
|
||||
union {
|
||||
struct {
|
||||
UA_DataSetMessage *dataSetMessages;
|
||||
size_t dataSetMessagesSize; /* Goes into the payload header */
|
||||
UA_DataSetMessage *dataSetMessages;
|
||||
} dataSetPayload;
|
||||
/* Extended with other payload types in the future */
|
||||
/* TODO: Add support for Discovery Messages */
|
||||
} payload;
|
||||
|
||||
UA_ByteString securityFooter;
|
||||
@ -202,46 +188,74 @@ UA_NetworkMessage_clear(UA_NetworkMessage* p);
|
||||
|
||||
/**
|
||||
* NetworkMessage Encoding
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* The en/decoding translates the NetworkMessage structure to/from a binary or
|
||||
* JSON encoding. The en/decoding of PubSub NetworkMessages can require
|
||||
* additional metadata. For example, during decoding, the DataType of raw
|
||||
* encoded fields must be already known. As an example for encoding, the
|
||||
* ``configuredSize`` may define zero-padding after a DataSetMessage.
|
||||
*
|
||||
* In the below methods, the different encoding options can be a NULL pointer
|
||||
* and will then be ignored. */
|
||||
|
||||
typedef struct {
|
||||
/* The WriterId is used to find the matching encoding metadata. If the
|
||||
* NetworkMessage/DataSetMessage does not transmit the identifier, then the
|
||||
* encoding metadata is used in-order for the received fields. */
|
||||
UA_UInt16 dataSetWriterId;
|
||||
|
||||
/* FieldMetaData for JSON and RAW encoding */
|
||||
size_t fieldsSize;
|
||||
UA_FieldMetaData *fields;
|
||||
|
||||
/* Zero-padding if the DataSetMessage is shorter (UADP) */
|
||||
UA_UInt16 configuredSize;
|
||||
} UA_DataSetMessage_EncodingMetaData;
|
||||
|
||||
typedef struct {
|
||||
size_t metaDataSize;
|
||||
UA_DataSetMessage_EncodingMetaData *metaData;
|
||||
} UA_NetworkMessage_EncodingOptions;
|
||||
|
||||
/* The output buffer is allocated to the required size if initially empty.
|
||||
* Otherwise, upon success, the length is adjusted. */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src,
|
||||
UA_ByteString *outBuf);
|
||||
UA_ByteString *outBuf,
|
||||
const UA_NetworkMessage_EncodingOptions *eo);
|
||||
|
||||
UA_EXPORT size_t
|
||||
UA_NetworkMessage_calcSizeBinary(const UA_NetworkMessage *p);
|
||||
UA_NetworkMessage_calcSizeBinary(const UA_NetworkMessage *p,
|
||||
const UA_NetworkMessage_EncodingOptions *eo);
|
||||
|
||||
/* The customTypes can be NULL */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_NetworkMessage_decodeBinary(const UA_ByteString *src,
|
||||
UA_NetworkMessage* dst,
|
||||
const UA_DecodeBinaryOptions *options);
|
||||
const UA_NetworkMessage_EncodingOptions *eo,
|
||||
const UA_DecodeBinaryOptions *bo);
|
||||
|
||||
#ifdef UA_ENABLE_JSON_ENCODING
|
||||
|
||||
/* The output buffer is allocated to the required size if initially empty.
|
||||
* Otherwise, upon success, the length is adjusted.
|
||||
* The encoding options can be NULL. */
|
||||
* Otherwise, upon success, the length is adjusted. */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_NetworkMessage_encodeJson(const UA_NetworkMessage *src,
|
||||
UA_ByteString *outBuf,
|
||||
const UA_EncodeJsonOptions *options);
|
||||
const UA_NetworkMessage_EncodingOptions *eo,
|
||||
const UA_EncodeJsonOptions *jo);
|
||||
|
||||
/* The encoding options can be NULL */
|
||||
UA_EXPORT size_t
|
||||
UA_NetworkMessage_calcSizeJson(const UA_NetworkMessage *src,
|
||||
const UA_EncodeJsonOptions *options);
|
||||
const UA_NetworkMessage_EncodingOptions *eo,
|
||||
const UA_EncodeJsonOptions *jo);
|
||||
|
||||
/* The encoding options can be NULL */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_NetworkMessage_decodeJson(const UA_ByteString *src,
|
||||
UA_NetworkMessage *dst,
|
||||
const UA_DecodeJsonOptions *options);
|
||||
|
||||
#endif
|
||||
const UA_NetworkMessage_EncodingOptions *eo,
|
||||
const UA_DecodeJsonOptions *jo);
|
||||
|
||||
#endif /* UA_ENABLE_JSON_ENCODING */
|
||||
#endif /* UA_ENABLE_PUBSUB */
|
||||
|
||||
_UA_END_DECLS
|
||||
|
@ -2,8 +2,9 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Tino Bischoff)
|
||||
* Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Tino Bischoff)
|
||||
* Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
|
||||
* Copyright (c) 2025 Fraunhofer IOSB (Author: Julius Pfrommer)
|
||||
*/
|
||||
|
||||
#ifndef UA_PUBSUB_NETWORKMESSAGE_H_
|
||||
@ -13,95 +14,121 @@
|
||||
#include <open62541/types_generated.h>
|
||||
#include <open62541/plugin/securitypolicy.h>
|
||||
#include <open62541/pubsub.h>
|
||||
#include <open62541/server_pubsub.h>
|
||||
|
||||
#include "../ua_types_encoding_binary.h"
|
||||
#include "../ua_types_encoding_json.h"
|
||||
|
||||
#ifdef UA_ENABLE_PUBSUB
|
||||
|
||||
_UA_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* DataSetMessage
|
||||
* ^^^^^^^^^^^^^^ */
|
||||
typedef struct {
|
||||
Ctx ctx;
|
||||
UA_NetworkMessage_EncodingOptions eo;
|
||||
UA_PubSubOffsetTable *ot;
|
||||
} PubSubEncodeCtx;
|
||||
|
||||
typedef struct {
|
||||
Ctx ctx;
|
||||
UA_NetworkMessage_EncodingOptions eo;
|
||||
} PubSubDecodeCtx;
|
||||
|
||||
typedef struct {
|
||||
CtxJson ctx;
|
||||
UA_NetworkMessage_EncodingOptions eo;
|
||||
} PubSubEncodeJsonCtx;
|
||||
|
||||
typedef struct {
|
||||
ParseCtx ctx;
|
||||
UA_NetworkMessage_EncodingOptions eo;
|
||||
} PubSubDecodeJsonCtx;
|
||||
|
||||
const UA_FieldMetaData *
|
||||
getFieldMetaData(const UA_DataSetMessage_EncodingMetaData *emd,
|
||||
size_t index);
|
||||
|
||||
const UA_DataSetMessage_EncodingMetaData *
|
||||
findEncodingMetaData(const UA_NetworkMessage_EncodingOptions *eo,
|
||||
const UA_DataSetMessage *dsm);
|
||||
|
||||
/******************/
|
||||
/* DataSetMessage */
|
||||
/******************/
|
||||
|
||||
UA_StatusCode
|
||||
UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader *src,
|
||||
UA_Byte **bufPos, const UA_Byte *bufEnd);
|
||||
UA_DataSetMessageHeader_encodeBinary(PubSubEncodeCtx *ctx,
|
||||
const UA_DataSetMessageHeader *src);
|
||||
|
||||
UA_StatusCode
|
||||
UA_DataSetMessageHeader_decodeBinary(Ctx *ctx, UA_DataSetMessageHeader *dst);
|
||||
UA_DataSetMessageHeader_decodeBinary(PubSubDecodeCtx *ctx,
|
||||
UA_DataSetMessageHeader *dst);
|
||||
|
||||
UA_StatusCode
|
||||
UA_DataSetMessage_encodeBinary(const UA_DataSetMessage *src, UA_Byte **bufPos,
|
||||
const UA_Byte *bufEnd);
|
||||
UA_DataSetMessage_encodeBinary(PubSubEncodeCtx *ctx,
|
||||
const UA_DataSetMessage_EncodingMetaData *emd,
|
||||
const UA_DataSetMessage *src);
|
||||
|
||||
UA_StatusCode
|
||||
UA_DataSetMessage_decodeBinary(Ctx *ctx, UA_DataSetMessage *dst, UA_UInt16 dsmSize);
|
||||
UA_DataSetMessage_decodeBinary(PubSubDecodeCtx *ctx,
|
||||
UA_DataSetMessage *dsm,
|
||||
size_t dsmSize);
|
||||
|
||||
size_t
|
||||
UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage *p, UA_PubSubOffsetTable *ot,
|
||||
UA_DataSetMessage_calcSizeBinary(PubSubEncodeCtx *ctx,
|
||||
const UA_DataSetMessage_EncodingMetaData *em,
|
||||
UA_DataSetMessage *src,
|
||||
size_t currentOffset);
|
||||
|
||||
void UA_DataSetMessage_clear(UA_DataSetMessage *p);
|
||||
|
||||
/**
|
||||
* NetworkMessage Encoding
|
||||
* ^^^^^^^^^^^^^^^^^^^^^^^ */
|
||||
/******************/
|
||||
/* NetworkMessage */
|
||||
/******************/
|
||||
|
||||
size_t
|
||||
UA_NetworkMessage_calcSizeBinaryWithOffsetTable(const UA_NetworkMessage *p,
|
||||
UA_PubSubOffsetTable *ot);
|
||||
UA_NetworkMessage_calcSizeBinaryInternal(PubSubEncodeCtx *ctx,
|
||||
const UA_NetworkMessage *src);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage *src,
|
||||
UA_Byte **bufPos, const UA_Byte *bufEnd);
|
||||
UA_NetworkMessage_encodeHeaders(PubSubEncodeCtx *ctx,
|
||||
const UA_NetworkMessage *src);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodePayload(const UA_NetworkMessage *src,
|
||||
UA_Byte **bufPos, const UA_Byte *bufEnd);
|
||||
UA_NetworkMessage_encodePayload(PubSubEncodeCtx *ctx,
|
||||
const UA_NetworkMessage *src);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodeFooters(const UA_NetworkMessage *src,
|
||||
UA_Byte **bufPos, const UA_Byte *bufEnd);
|
||||
|
||||
/**
|
||||
* NetworkMessage Decoding
|
||||
* ^^^^^^^^^^^^^^^^^^^^^^^ */
|
||||
UA_NetworkMessage_encodeFooters(PubSubEncodeCtx *ctx,
|
||||
const UA_NetworkMessage *src);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_decodeHeaders(Ctx *ctx, UA_NetworkMessage *dst);
|
||||
UA_NetworkMessage_decodeHeaders(PubSubDecodeCtx *ctx,
|
||||
UA_NetworkMessage *dst);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_decodePayload(Ctx *ctx, UA_NetworkMessage *dst);
|
||||
UA_NetworkMessage_decodePayload(PubSubDecodeCtx *ctx,
|
||||
UA_NetworkMessage *dst);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_decodeFooters(Ctx *ctx, UA_NetworkMessage *dst);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodeJsonInternal(const UA_NetworkMessage *src,
|
||||
UA_Byte **bufPos, const UA_Byte **bufEnd,
|
||||
UA_NamespaceMapping *namespaceMapping,
|
||||
UA_String *serverUris, size_t serverUriSize,
|
||||
UA_Boolean useReversible);
|
||||
|
||||
size_t
|
||||
UA_NetworkMessage_calcSizeJsonInternal(const UA_NetworkMessage *src,
|
||||
UA_NamespaceMapping *namespaceMapping,
|
||||
UA_String *serverUris, size_t serverUriSize,
|
||||
UA_Boolean useReversible);
|
||||
UA_NetworkMessage_decodeFooters(PubSubDecodeCtx *ctx,
|
||||
UA_NetworkMessage *dst);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodeBinaryWithEncryptStart(const UA_NetworkMessage* src,
|
||||
UA_Byte **bufPos, const UA_Byte *bufEnd,
|
||||
UA_NetworkMessage_encodeBinaryWithEncryptStart(PubSubEncodeCtx *ctx,
|
||||
const UA_NetworkMessage *src,
|
||||
UA_Byte **dataToEncryptStart);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode securityMode,
|
||||
UA_PubSubSecurityPolicy *policy, void *policyContext,
|
||||
UA_Byte *messageStart, UA_Byte *encryptStart,
|
||||
UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm,
|
||||
UA_MessageSecurityMode securityMode,
|
||||
UA_PubSubSecurityPolicy *policy,
|
||||
void *policyContext,
|
||||
UA_Byte *messageStart,
|
||||
UA_Byte *encryptStart,
|
||||
UA_Byte *sigStart);
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodeJsonInternal(PubSubEncodeJsonCtx *ctx,
|
||||
const UA_NetworkMessage *src);
|
||||
|
||||
_UA_END_DECLS
|
||||
|
||||
#endif /* UA_ENABLE_PUBSUB */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@ const char * UA_DECODEKEY_PAYLOAD = "Payload";
|
||||
const char * UA_DECODEKEY_DS_TYPE = "Type";
|
||||
|
||||
/* -- json encoding/decoding -- */
|
||||
static UA_StatusCode writeJsonKey_UA_String(CtxJson *ctx, UA_String *in) {
|
||||
static UA_StatusCode writeJsonKey_UA_String(CtxJson *ctx, const UA_String *in) {
|
||||
UA_STACKARRAY(char, out, in->length + 1);
|
||||
memcpy(out, in->data, in->length);
|
||||
out[in->length] = 0;
|
||||
@ -36,8 +36,9 @@ static UA_StatusCode writeJsonKey_UA_String(CtxJson *ctx, UA_String *in) {
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UA_DataSetMessage_encodeJson_internal(const UA_DataSetMessage* src,
|
||||
CtxJson *ctx) {
|
||||
UA_DataSetMessage_encodeJson_internal(CtxJson *ctx,
|
||||
const UA_DataSetMessage_EncodingMetaData *emd,
|
||||
const UA_DataSetMessage *src) {
|
||||
status rv = writeJsonObjStart(ctx);
|
||||
|
||||
/* DataSetWriterId */
|
||||
@ -106,25 +107,27 @@ UA_DataSetMessage_encodeJson_internal(const UA_DataSetMessage* src,
|
||||
|
||||
if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
|
||||
/* Variant */
|
||||
for(UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
|
||||
if(src->data.keyFrameData.fieldNames)
|
||||
rv |= writeJsonKey_UA_String(ctx, &src->data.keyFrameData.fieldNames[i]);
|
||||
for(UA_UInt16 i = 0; i < src->fieldCount; i++) {
|
||||
const UA_FieldMetaData *fmd = getFieldMetaData(emd, i);
|
||||
if(fmd)
|
||||
rv |= writeJsonKey_UA_String(ctx, &fmd->name);
|
||||
else
|
||||
rv |= writeJsonKey(ctx, "");
|
||||
rv |= encodeJsonJumpTable[UA_DATATYPEKIND_VARIANT]
|
||||
(ctx, &src->data.keyFrameData.dataSetFields[i].value, NULL);
|
||||
(ctx, &src->data.keyFrameFields[i].value, NULL);
|
||||
if(rv != UA_STATUSCODE_GOOD)
|
||||
return rv;
|
||||
}
|
||||
} else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
|
||||
/* DataValue */
|
||||
for(UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
|
||||
if(src->data.keyFrameData.fieldNames)
|
||||
rv |= writeJsonKey_UA_String(ctx, &src->data.keyFrameData.fieldNames[i]);
|
||||
for(UA_UInt16 i = 0; i < src->fieldCount; i++) {
|
||||
const UA_FieldMetaData *fmd = getFieldMetaData(emd, i);
|
||||
if(fmd)
|
||||
rv |= writeJsonKey_UA_String(ctx, &fmd->name);
|
||||
else
|
||||
rv |= writeJsonKey(ctx, "");
|
||||
rv |= encodeJsonJumpTable[UA_DATATYPEKIND_DATAVALUE]
|
||||
(ctx, &src->data.keyFrameData.dataSetFields[i], NULL);
|
||||
(ctx, &src->data.keyFrameFields[i], NULL);
|
||||
if(rv != UA_STATUSCODE_GOOD)
|
||||
return rv;
|
||||
}
|
||||
@ -137,24 +140,25 @@ UA_DataSetMessage_encodeJson_internal(const UA_DataSetMessage* src,
|
||||
return rv;
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UA_NetworkMessage_encodeJson_internal(const UA_NetworkMessage* src, CtxJson *ctx) {
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodeJsonInternal(PubSubEncodeJsonCtx *ctx,
|
||||
const UA_NetworkMessage *src) {
|
||||
/* currently only ua-data is supported, no discovery message implemented */
|
||||
if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
|
||||
return UA_STATUSCODE_BADNOTIMPLEMENTED;
|
||||
|
||||
status rv = writeJsonObjStart(ctx);
|
||||
status rv = writeJsonObjStart(&ctx->ctx);
|
||||
|
||||
/* Table 91 – JSON NetworkMessage Definition
|
||||
* MessageId | String | A globally unique identifier for the message.
|
||||
* This value is mandatory. But we don't check uniqueness in the
|
||||
* encoding layer. */
|
||||
rv |= writeJsonObjElm(ctx, UA_DECODEKEY_MESSAGEID,
|
||||
rv |= writeJsonObjElm(&ctx->ctx, UA_DECODEKEY_MESSAGEID,
|
||||
&src->messageId, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
/* MessageType */
|
||||
UA_String s = UA_STRING("ua-data");
|
||||
rv |= writeJsonObjElm(ctx, UA_DECODEKEY_MESSAGETYPE,
|
||||
rv |= writeJsonObjElm(&ctx->ctx, UA_DECODEKEY_MESSAGETYPE,
|
||||
&s, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
/* PublisherId, always encode as a JSON string */
|
||||
@ -166,8 +170,8 @@ UA_NetworkMessage_encodeJson_internal(const UA_NetworkMessage* src, CtxJson *ctx
|
||||
rv |= UA_encodeJson(v.data, v.type, &bs, NULL);
|
||||
if(rv != UA_STATUSCODE_GOOD)
|
||||
return rv;
|
||||
rv |= writeJsonKey(ctx, UA_DECODEKEY_PUBLISHERID);
|
||||
rv |= encodeJsonJumpTable[UA_DATATYPEKIND_STRING](ctx, &bs, NULL);
|
||||
rv |= writeJsonKey(&ctx->ctx, UA_DECODEKEY_PUBLISHERID);
|
||||
rv |= encodeJsonJumpTable[UA_DATATYPEKIND_STRING](&ctx->ctx, &bs, NULL);
|
||||
}
|
||||
if(rv != UA_STATUSCODE_GOOD)
|
||||
return rv;
|
||||
@ -176,7 +180,7 @@ UA_NetworkMessage_encodeJson_internal(const UA_NetworkMessage* src, CtxJson *ctx
|
||||
|
||||
/* DataSetClassId */
|
||||
if(src->dataSetClassIdEnabled) {
|
||||
rv |= writeJsonObjElm(ctx, UA_DECODEKEY_DATASETCLASSID,
|
||||
rv |= writeJsonObjElm(&ctx->ctx, UA_DECODEKEY_DATASETCLASSID,
|
||||
&src->dataSetClassId, &UA_TYPES[UA_TYPES_GUID]);
|
||||
if(rv != UA_STATUSCODE_GOOD)
|
||||
return rv;
|
||||
@ -185,60 +189,36 @@ UA_NetworkMessage_encodeJson_internal(const UA_NetworkMessage* src, CtxJson *ctx
|
||||
/* Payload: DataSetMessages */
|
||||
size_t count = src->payload.dataSetPayload.dataSetMessagesSize;
|
||||
if(count > 0) {
|
||||
rv |= writeJsonKey(ctx, UA_DECODEKEY_MESSAGES);
|
||||
rv |= writeJsonArrStart(ctx); /* start array */
|
||||
|
||||
const UA_DataSetMessage *dataSetMessages =
|
||||
src->payload.dataSetPayload.dataSetMessages;
|
||||
rv |= writeJsonKey(&ctx->ctx, UA_DECODEKEY_MESSAGES);
|
||||
rv |= writeJsonArrStart(&ctx->ctx); /* start array */
|
||||
const UA_DataSetMessage *dsm = src->payload.dataSetPayload.dataSetMessages;
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
rv |= writeJsonBeforeElement(ctx, true);
|
||||
rv |= UA_DataSetMessage_encodeJson_internal(&dataSetMessages[i], ctx);
|
||||
const UA_DataSetMessage_EncodingMetaData *emd =
|
||||
findEncodingMetaData(&ctx->eo, &dsm[i]);
|
||||
rv |= writeJsonBeforeElement(&ctx->ctx, true);
|
||||
rv |= UA_DataSetMessage_encodeJson_internal(&ctx->ctx, emd, &dsm[i]);
|
||||
if(rv != UA_STATUSCODE_GOOD)
|
||||
return rv;
|
||||
/* comma is needed if more dsm are present */
|
||||
ctx->commaNeeded[ctx->depth] = true;
|
||||
ctx->ctx.commaNeeded[ctx->ctx.depth] = true;
|
||||
}
|
||||
|
||||
rv |= writeJsonArrEnd(ctx, NULL); /* end array */
|
||||
rv |= writeJsonArrEnd(&ctx->ctx, NULL); /* end array */
|
||||
}
|
||||
|
||||
rv |= writeJsonObjEnd(ctx);
|
||||
rv |= writeJsonObjEnd(&ctx->ctx);
|
||||
return rv;
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodeJsonInternal(const UA_NetworkMessage *src,
|
||||
UA_Byte **bufPos, const UA_Byte **bufEnd,
|
||||
UA_NamespaceMapping *namespaceMapping,
|
||||
UA_String *serverUris, size_t serverUriSize,
|
||||
UA_Boolean useReversible) {
|
||||
/* Set up the context */
|
||||
CtxJson ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.pos = *bufPos;
|
||||
ctx.end = *bufEnd;
|
||||
ctx.depth = 0;
|
||||
ctx.namespaceMapping = namespaceMapping;
|
||||
ctx.serverUris = serverUris;
|
||||
ctx.serverUrisSize = serverUriSize;
|
||||
ctx.useReversible = useReversible;
|
||||
ctx.calcOnly = false;
|
||||
|
||||
status ret = UA_NetworkMessage_encodeJson_internal(src, &ctx);
|
||||
|
||||
*bufPos = ctx.pos;
|
||||
*bufEnd = ctx.end;
|
||||
return ret;
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_encodeJson(const UA_NetworkMessage *src,
|
||||
UA_ByteString *outBuf,
|
||||
const UA_EncodeJsonOptions *options) {
|
||||
const UA_NetworkMessage_EncodingOptions *eo,
|
||||
const UA_EncodeJsonOptions *jo) {
|
||||
UA_Boolean alloced = (outBuf->length == 0);
|
||||
UA_StatusCode ret = UA_STATUSCODE_GOOD;
|
||||
if(alloced) {
|
||||
size_t length = UA_NetworkMessage_calcSizeJson(src, options);
|
||||
size_t length = UA_NetworkMessage_calcSizeJson(src, eo, jo);
|
||||
if(length == 0)
|
||||
return UA_STATUSCODE_BADENCODINGERROR;
|
||||
ret = UA_ByteString_allocBuffer(outBuf, length);
|
||||
@ -247,139 +227,131 @@ UA_NetworkMessage_encodeJson(const UA_NetworkMessage *src,
|
||||
}
|
||||
|
||||
/* Set up the context */
|
||||
CtxJson ctx;
|
||||
PubSubEncodeJsonCtx ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.pos = outBuf->data;
|
||||
ctx.end = ctx.pos + outBuf->length;
|
||||
ctx.calcOnly = false;
|
||||
if(options) {
|
||||
ctx.useReversible = options->useReversible;
|
||||
ctx.namespaceMapping = options->namespaceMapping;
|
||||
ctx.serverUrisSize = options->serverUrisSize;
|
||||
ctx.serverUris = options->serverUris;
|
||||
ctx.prettyPrint = options->prettyPrint;
|
||||
ctx.unquotedKeys = options->unquotedKeys;
|
||||
ctx.stringNodeIds = options->stringNodeIds;
|
||||
ctx.ctx.pos = outBuf->data;
|
||||
ctx.ctx.end = outBuf->data + outBuf->length;
|
||||
ctx.ctx.calcOnly = false;
|
||||
if(eo)
|
||||
ctx.eo = *eo;
|
||||
if(jo) {
|
||||
ctx.ctx.useReversible = jo->useReversible;
|
||||
ctx.ctx.namespaceMapping = jo->namespaceMapping;
|
||||
ctx.ctx.serverUrisSize = jo->serverUrisSize;
|
||||
ctx.ctx.serverUris = jo->serverUris;
|
||||
ctx.ctx.prettyPrint = jo->prettyPrint;
|
||||
ctx.ctx.unquotedKeys = jo->unquotedKeys;
|
||||
ctx.ctx.stringNodeIds = jo->stringNodeIds;
|
||||
}
|
||||
|
||||
ret = UA_NetworkMessage_encodeJson_internal(src, &ctx);
|
||||
ret = UA_NetworkMessage_encodeJsonInternal(&ctx, src);
|
||||
|
||||
/* In case the buffer was supplied externally and is longer than the encoded
|
||||
* string */
|
||||
if(UA_LIKELY(ret == UA_STATUSCODE_GOOD))
|
||||
outBuf->length = (size_t)((uintptr_t)ctx.pos - (uintptr_t)outBuf->data);
|
||||
outBuf->length = (size_t)((uintptr_t)ctx.ctx.pos - (uintptr_t)outBuf->data);
|
||||
|
||||
if(alloced && ret != UA_STATUSCODE_GOOD)
|
||||
UA_String_clear(outBuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
UA_NetworkMessage_calcSizeJsonInternal(const UA_NetworkMessage *src,
|
||||
UA_NamespaceMapping *namespaceMapping,
|
||||
UA_String *serverUris, size_t serverUriSize,
|
||||
UA_Boolean useReversible) {
|
||||
/* Set up the context */
|
||||
CtxJson ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.pos = 0;
|
||||
ctx.end = (const UA_Byte*)(uintptr_t)SIZE_MAX;
|
||||
ctx.depth = 0;
|
||||
ctx.namespaceMapping = namespaceMapping;
|
||||
ctx.serverUris = serverUris;
|
||||
ctx.serverUrisSize = serverUriSize;
|
||||
ctx.useReversible = useReversible;
|
||||
ctx.calcOnly = true;
|
||||
|
||||
status ret = UA_NetworkMessage_encodeJson_internal(src, &ctx);
|
||||
if(ret != UA_STATUSCODE_GOOD)
|
||||
return 0;
|
||||
return (size_t)ctx.pos;
|
||||
}
|
||||
|
||||
size_t
|
||||
UA_NetworkMessage_calcSizeJson(const UA_NetworkMessage *src,
|
||||
const UA_EncodeJsonOptions *options) {
|
||||
const UA_NetworkMessage_EncodingOptions *eo,
|
||||
const UA_EncodeJsonOptions *jo) {
|
||||
/* Set up the context */
|
||||
CtxJson ctx;
|
||||
PubSubEncodeJsonCtx ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.end = (const UA_Byte*)(uintptr_t)SIZE_MAX;
|
||||
ctx.calcOnly = true;
|
||||
if(options) {
|
||||
ctx.useReversible = options->useReversible;
|
||||
ctx.namespaceMapping = options->namespaceMapping;
|
||||
ctx.serverUrisSize = options->serverUrisSize;
|
||||
ctx.serverUris = options->serverUris;
|
||||
ctx.prettyPrint = options->prettyPrint;
|
||||
ctx.unquotedKeys = options->unquotedKeys;
|
||||
ctx.stringNodeIds = options->stringNodeIds;
|
||||
ctx.ctx.end = (const UA_Byte*)(uintptr_t)SIZE_MAX;
|
||||
ctx.ctx.calcOnly = true;
|
||||
if(eo)
|
||||
ctx.eo = *eo;
|
||||
if(jo) {
|
||||
ctx.ctx.useReversible = jo->useReversible;
|
||||
ctx.ctx.namespaceMapping = jo->namespaceMapping;
|
||||
ctx.ctx.serverUrisSize = jo->serverUrisSize;
|
||||
ctx.ctx.serverUris = jo->serverUris;
|
||||
ctx.ctx.prettyPrint = jo->prettyPrint;
|
||||
ctx.ctx.unquotedKeys = jo->unquotedKeys;
|
||||
ctx.ctx.stringNodeIds = jo->stringNodeIds;
|
||||
}
|
||||
|
||||
status ret = UA_NetworkMessage_encodeJson_internal(src, &ctx);
|
||||
status ret = UA_NetworkMessage_encodeJsonInternal(&ctx, src);
|
||||
if(ret != UA_STATUSCODE_GOOD)
|
||||
return 0;
|
||||
|
||||
return (size_t)ctx.pos;
|
||||
return (size_t)ctx.ctx.pos;
|
||||
}
|
||||
|
||||
/* decode json */
|
||||
static status
|
||||
MetaDataVersion_decodeJsonInternal(ParseCtx *ctx, void* cvd, const UA_DataType *type) {
|
||||
MetaDataVersion_decodeJsonInternal(ParseCtx *ctx, void* cvd, const UA_DataType *_) {
|
||||
return decodeJsonJumpTable[UA_DATATYPEKIND_STRUCTURE]
|
||||
(ctx, cvd, &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE]);
|
||||
}
|
||||
|
||||
static size_t
|
||||
decodingFieldIndex(const UA_DataSetMessage_EncodingMetaData *emd,
|
||||
UA_String name, size_t origIndex) {
|
||||
if(!emd)
|
||||
return origIndex;
|
||||
for(size_t i = 0; i < emd->fieldsSize; i++) {
|
||||
if(UA_String_equal(&name, &emd->fields[i].name))
|
||||
return i;
|
||||
}
|
||||
return origIndex;
|
||||
}
|
||||
|
||||
static status
|
||||
DataSetPayload_decodeJsonInternal(ParseCtx *ctx, void* dsmP, const UA_DataType *type) {
|
||||
UA_DataSetMessage* dsm = (UA_DataSetMessage*)dsmP;
|
||||
DataSetPayload_decodeJsonInternal(PubSubDecodeJsonCtx *ctx,
|
||||
UA_DataSetMessage *dsm,
|
||||
const UA_DataType *_) {
|
||||
dsm->header.dataSetMessageValid = true;
|
||||
if(currentTokenType(ctx) == CJ5_TOKEN_NULL) {
|
||||
ctx->index++;
|
||||
if(currentTokenType(&ctx->ctx) == CJ5_TOKEN_NULL) {
|
||||
ctx->ctx.index++;
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
if(currentTokenType(ctx) != CJ5_TOKEN_OBJECT)
|
||||
if(currentTokenType(&ctx->ctx) != CJ5_TOKEN_OBJECT)
|
||||
return UA_STATUSCODE_BADDECODINGERROR;
|
||||
|
||||
/* The number of key-value pairs */
|
||||
UA_assert(ctx->tokens[ctx->index].size % 2 == 0);
|
||||
size_t length = (size_t)(ctx->tokens[ctx->index].size) / 2;
|
||||
UA_assert(ctx->ctx.tokens[ctx->ctx.index].size % 2 == 0);
|
||||
size_t length = (size_t)(ctx->ctx.tokens[ctx->ctx.index].size) / 2;
|
||||
|
||||
UA_String *fieldNames = (UA_String*)UA_calloc(length, sizeof(UA_String));
|
||||
if(!fieldNames)
|
||||
dsm->data.keyFrameFields = (UA_DataValue *)
|
||||
UA_Array_new(length, &UA_TYPES[UA_TYPES_DATAVALUE]);
|
||||
if(!dsm->data.keyFrameFields)
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
dsm->data.keyFrameData.fieldNames = fieldNames;
|
||||
dsm->data.keyFrameData.fieldCount = (UA_UInt16)length;
|
||||
dsm->fieldCount = (UA_UInt16)length;
|
||||
|
||||
dsm->data.keyFrameData.dataSetFields = (UA_DataValue *)
|
||||
UA_Array_new(dsm->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
|
||||
if(!dsm->data.keyFrameData.dataSetFields)
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
dsm->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
|
||||
|
||||
ctx->index++; /* Go to the first key */
|
||||
const UA_DataSetMessage_EncodingMetaData *emd = findEncodingMetaData(&ctx->eo, dsm);
|
||||
|
||||
/* Iterate over the key/value pairs in the object. Keys are stored in fieldnames. */
|
||||
ctx->ctx.index++; /* Go to the first key */
|
||||
status ret = UA_STATUSCODE_GOOD;
|
||||
dsm->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
|
||||
for(size_t i = 0; i < length; ++i) {
|
||||
UA_assert(currentTokenType(ctx) == CJ5_TOKEN_STRING);
|
||||
ret = decodeJsonJumpTable[UA_DATATYPEKIND_STRING](ctx, &fieldNames[i], type);
|
||||
if(ret != UA_STATUSCODE_GOOD)
|
||||
return ret;
|
||||
UA_assert(currentTokenType(&ctx->ctx) == CJ5_TOKEN_STRING);
|
||||
UA_String fieldName = UA_STRING_NULL;
|
||||
ret = decodeJsonJumpTable[UA_DATATYPEKIND_STRING](&ctx->ctx, &fieldName, NULL);
|
||||
UA_CHECK_STATUS(ret, return ret);
|
||||
|
||||
/* TODO: Is field value a variant or datavalue? */
|
||||
size_t index = decodingFieldIndex(emd, fieldName, i);
|
||||
UA_DataValue_clear(&dsm->data.keyFrameFields[index]);
|
||||
UA_String_clear(&fieldName);
|
||||
ret = decodeJsonJumpTable[UA_DATATYPEKIND_DATAVALUE]
|
||||
(ctx, &dsm->data.keyFrameData.dataSetFields[i], NULL);
|
||||
|
||||
if(ret != UA_STATUSCODE_GOOD)
|
||||
return ret;
|
||||
(&ctx->ctx, &dsm->data.keyFrameFields[index], NULL);
|
||||
UA_CHECK_STATUS(ret, return ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static status
|
||||
DatasetMessage_Payload_decodeJsonInternal(ParseCtx *ctx, UA_DataSetMessage* dsm,
|
||||
DatasetMessage_Payload_decodeJsonInternal(PubSubDecodeJsonCtx *ctx, UA_DataSetMessage* dsm,
|
||||
const UA_DataType *type) {
|
||||
UA_ConfigurationVersionDataType cvd;
|
||||
DecodeEntry entries[7] = {
|
||||
@ -389,14 +361,15 @@ DatasetMessage_Payload_decodeJsonInternal(ParseCtx *ctx, UA_DataSetMessage* dsm,
|
||||
{UA_DECODEKEY_TIMESTAMP, &dsm->header.timestamp, NULL, false, &UA_TYPES[UA_TYPES_DATETIME]},
|
||||
{UA_DECODEKEY_DSM_STATUS, &dsm->header.status, NULL, false, &UA_TYPES[UA_TYPES_UINT16]},
|
||||
{UA_DECODEKEY_MESSAGETYPE, NULL, NULL, false, NULL},
|
||||
{UA_DECODEKEY_PAYLOAD, dsm, &DataSetPayload_decodeJsonInternal, false, NULL}
|
||||
{UA_DECODEKEY_PAYLOAD, dsm, (decodeJsonSignature)DataSetPayload_decodeJsonInternal, false, NULL}
|
||||
};
|
||||
status ret = decodeFields(ctx, entries, 7);
|
||||
status ret = decodeFields(&ctx->ctx, entries, 7);
|
||||
|
||||
/* Error or no DatasetWriterId found or no payload found */
|
||||
if(ret != UA_STATUSCODE_GOOD || !entries[0].found || !entries[6].found)
|
||||
return UA_STATUSCODE_BADDECODINGERROR;
|
||||
|
||||
/* TODO: Check FieldEncoding1 and FieldEncoding2 to determine the field encoding */
|
||||
dsm->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
|
||||
dsm->header.dataSetMessageSequenceNrEnabled = entries[1].found;
|
||||
dsm->header.configVersionMajorVersion = cvd.majorVersion;
|
||||
@ -414,20 +387,20 @@ DatasetMessage_Payload_decodeJsonInternal(ParseCtx *ctx, UA_DataSetMessage* dsm,
|
||||
}
|
||||
|
||||
static status
|
||||
DatasetMessage_Array_decodeJsonInternal(ParseCtx *ctx, void *UA_RESTRICT dst,
|
||||
DatasetMessage_Array_decodeJsonInternal(PubSubDecodeJsonCtx *ctx, void *UA_RESTRICT dst,
|
||||
const UA_DataType *type) {
|
||||
/* Array or object */
|
||||
size_t length = 1;
|
||||
if(currentTokenType(ctx) == CJ5_TOKEN_ARRAY) {
|
||||
length = (size_t)ctx->tokens[ctx->index].size;
|
||||
if(currentTokenType(&ctx->ctx) == CJ5_TOKEN_ARRAY) {
|
||||
length = (size_t)ctx->ctx.tokens[ctx->ctx.index].size;
|
||||
|
||||
/* Go to the first array member */
|
||||
ctx->index++;
|
||||
ctx->ctx.index++;
|
||||
|
||||
/* Return early for empty arrays */
|
||||
if(length == 0)
|
||||
return UA_STATUSCODE_GOOD;
|
||||
} else if(currentTokenType(ctx) != CJ5_TOKEN_OBJECT) {
|
||||
} else if(currentTokenType(&ctx->ctx) != CJ5_TOKEN_OBJECT) {
|
||||
return UA_STATUSCODE_BADDECODINGERROR;
|
||||
}
|
||||
|
||||
@ -460,7 +433,8 @@ decodePublisherIdJsonInternal(ParseCtx *ctx, void *UA_RESTRICT dst,
|
||||
}
|
||||
|
||||
static status
|
||||
NetworkMessage_decodeJsonInternal(ParseCtx *ctx, UA_NetworkMessage *dst) {
|
||||
NetworkMessage_decodeJsonInternal(PubSubDecodeJsonCtx *ctx,
|
||||
UA_NetworkMessage *dst) {
|
||||
memset(dst, 0, sizeof(UA_NetworkMessage));
|
||||
dst->chunkMessage = false;
|
||||
dst->groupHeaderEnabled = false;
|
||||
@ -470,10 +444,10 @@ NetworkMessage_decodeJsonInternal(ParseCtx *ctx, UA_NetworkMessage *dst) {
|
||||
|
||||
/* Is Messages an Array? How big? */
|
||||
size_t searchResultMessages = 0;
|
||||
status found = lookAheadForKey(ctx, UA_DECODEKEY_MESSAGES, &searchResultMessages);
|
||||
status found = lookAheadForKey(&ctx->ctx, UA_DECODEKEY_MESSAGES, &searchResultMessages);
|
||||
if(found != UA_STATUSCODE_GOOD)
|
||||
return UA_STATUSCODE_BADNOTIMPLEMENTED;
|
||||
const cj5_token *bodyToken = &ctx->tokens[searchResultMessages];
|
||||
const cj5_token *bodyToken = &ctx->ctx.tokens[searchResultMessages];
|
||||
size_t messageCount = 1;
|
||||
if(bodyToken->type == CJ5_TOKEN_ARRAY)
|
||||
messageCount = (size_t)bodyToken->size;
|
||||
@ -481,11 +455,11 @@ NetworkMessage_decodeJsonInternal(ParseCtx *ctx, UA_NetworkMessage *dst) {
|
||||
/* MessageType */
|
||||
UA_Boolean isUaData = true;
|
||||
size_t searchResultMessageType = 0;
|
||||
found = lookAheadForKey(ctx, UA_DECODEKEY_MESSAGETYPE, &searchResultMessageType);
|
||||
found = lookAheadForKey(&ctx->ctx, UA_DECODEKEY_MESSAGETYPE, &searchResultMessageType);
|
||||
if(found != UA_STATUSCODE_GOOD)
|
||||
return UA_STATUSCODE_BADDECODINGERROR;
|
||||
size_t size = getTokenLength(&ctx->tokens[searchResultMessageType]);
|
||||
const char* msgType = &ctx->json5[ctx->tokens[searchResultMessageType].start];
|
||||
size_t size = getTokenLength(&ctx->ctx.tokens[searchResultMessageType]);
|
||||
const char* msgType = &ctx->ctx.json5[ctx->ctx.tokens[searchResultMessageType].start];
|
||||
if(size == 7) { //ua-data
|
||||
if(strncmp(msgType, "ua-data", size) != 0)
|
||||
return UA_STATUSCODE_BADDECODINGERROR;
|
||||
@ -516,10 +490,10 @@ NetworkMessage_decodeJsonInternal(ParseCtx *ctx, UA_NetworkMessage *dst) {
|
||||
{UA_DECODEKEY_PUBLISHERID, &dst->publisherId, decodePublisherIdJsonInternal, false, NULL},
|
||||
{UA_DECODEKEY_DATASETCLASSID, &dst->dataSetClassId, NULL, false, &UA_TYPES[UA_TYPES_GUID]},
|
||||
{UA_DECODEKEY_MESSAGES, dst->payload.dataSetPayload.dataSetMessages,
|
||||
&DatasetMessage_Array_decodeJsonInternal, false, NULL}
|
||||
(decodeJsonSignature)DatasetMessage_Array_decodeJsonInternal, false, NULL}
|
||||
};
|
||||
|
||||
status ret = decodeFields(ctx, entries, 5);
|
||||
status ret = decodeFields(&ctx->ctx, entries, 5);
|
||||
if(ret != UA_STATUSCODE_GOOD)
|
||||
return ret;
|
||||
|
||||
@ -534,20 +508,23 @@ NetworkMessage_decodeJsonInternal(ParseCtx *ctx, UA_NetworkMessage *dst) {
|
||||
UA_StatusCode
|
||||
UA_NetworkMessage_decodeJson(const UA_ByteString *src,
|
||||
UA_NetworkMessage *dst,
|
||||
const UA_DecodeJsonOptions *options) {
|
||||
const UA_NetworkMessage_EncodingOptions *eo,
|
||||
const UA_DecodeJsonOptions *jo) {
|
||||
/* Set up the context */
|
||||
cj5_token tokens[UA_JSON_MAXTOKENCOUNT];
|
||||
ParseCtx ctx;
|
||||
memset(&ctx, 0, sizeof(ParseCtx));
|
||||
ctx.tokens = tokens;
|
||||
if(options) {
|
||||
ctx.namespaceMapping = options->namespaceMapping;
|
||||
ctx.serverUrisSize = options->serverUrisSize;
|
||||
ctx.serverUris = options->serverUris;
|
||||
ctx.customTypes = options->customTypes;
|
||||
PubSubDecodeJsonCtx ctx;
|
||||
memset(&ctx, 0, sizeof(PubSubDecodeJsonCtx));
|
||||
ctx.ctx.tokens = tokens;
|
||||
if(eo)
|
||||
ctx.eo = *eo;
|
||||
if(jo) {
|
||||
ctx.ctx.namespaceMapping = jo->namespaceMapping;
|
||||
ctx.ctx.serverUrisSize = jo->serverUrisSize;
|
||||
ctx.ctx.serverUris = jo->serverUris;
|
||||
ctx.ctx.customTypes = jo->customTypes;
|
||||
}
|
||||
|
||||
status ret = tokenize(&ctx, src, UA_JSON_MAXTOKENCOUNT, NULL);
|
||||
status ret = tokenize(&ctx.ctx, src, UA_JSON_MAXTOKENCOUNT, NULL);
|
||||
if(ret != UA_STATUSCODE_GOOD)
|
||||
goto cleanup;
|
||||
|
||||
@ -557,7 +534,7 @@ UA_NetworkMessage_decodeJson(const UA_ByteString *src,
|
||||
|
||||
cleanup:
|
||||
/* Free token array on the heap */
|
||||
if(ctx.tokens != tokens)
|
||||
UA_free((void*)(uintptr_t)ctx.tokens);
|
||||
if(ctx.ctx.tokens != tokens)
|
||||
UA_free((void*)(uintptr_t)ctx.ctx.tokens);
|
||||
return ret;
|
||||
}
|
||||
|
@ -356,34 +356,18 @@ UA_PubSubDataSetWriter_generateKeyFrameMessage(UA_PubSubManager *psm,
|
||||
/* Prepare DataSetMessageContent */
|
||||
dataSetMessage->header.dataSetMessageValid = true;
|
||||
dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
|
||||
dataSetMessage->data.keyFrameData.fieldCount = pds->fieldSize;
|
||||
dataSetMessage->data.keyFrameData.dataSetFields = (UA_DataValue *)
|
||||
dataSetMessage->fieldCount = pds->fieldSize;
|
||||
dataSetMessage->data.keyFrameFields = (UA_DataValue *)
|
||||
UA_Array_new(pds->fieldSize, &UA_TYPES[UA_TYPES_DATAVALUE]);
|
||||
dataSetMessage->data.keyFrameData.dataSetMetaDataType = &pds->dataSetMetaData;
|
||||
if(!dataSetMessage->data.keyFrameData.dataSetFields)
|
||||
if(!dataSetMessage->data.keyFrameFields)
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
|
||||
#ifdef UA_ENABLE_JSON_ENCODING
|
||||
dataSetMessage->data.keyFrameData.fieldNames = (UA_String *)
|
||||
UA_Array_new(pds->fieldSize, &UA_TYPES[UA_TYPES_STRING]);
|
||||
if(!dataSetMessage->data.keyFrameData.fieldNames) {
|
||||
UA_DataSetMessage_clear(dataSetMessage);
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Loop over the fields */
|
||||
size_t counter = 0;
|
||||
UA_DataSetField *dsf;
|
||||
TAILQ_FOREACH(dsf, &pds->fields, listEntry) {
|
||||
#ifdef UA_ENABLE_JSON_ENCODING
|
||||
/* Set the field name alias */
|
||||
UA_String_copy(&dsf->config.field.variable.fieldNameAlias,
|
||||
&dataSetMessage->data.keyFrameData.fieldNames[counter]);
|
||||
#endif
|
||||
|
||||
/* Sample the value */
|
||||
UA_DataValue *dfv = &dataSetMessage->data.keyFrameData.dataSetFields[counter];
|
||||
UA_DataValue *dfv = &dataSetMessage->data.keyFrameFields[counter];
|
||||
UA_PubSubDataSetField_sampleValue(psm, dsf, dfv);
|
||||
|
||||
/* Deactivate statuscode? */
|
||||
@ -443,7 +427,7 @@ UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_PubSubManager *psm,
|
||||
UA_DataSetWriterSample *ls = &dsw->lastSamples[counter];
|
||||
if(!UA_Variant_equal(&ls->value.value, &value.value)) {
|
||||
/* increase fieldCount for current delta message */
|
||||
dsm->data.deltaFrameData.fieldCount++;
|
||||
dsm->fieldCount++;
|
||||
ls->valueChanged = true;
|
||||
|
||||
/* Update last stored sample */
|
||||
@ -463,8 +447,8 @@ UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_PubSubManager *psm,
|
||||
if(!deltaFields)
|
||||
return UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
|
||||
dsm->data.deltaFrameData.deltaFrameFields = deltaFields;
|
||||
dsm->data.deltaFrameData.fieldCount = counter;
|
||||
dsm->fieldCount = counter;
|
||||
dsm->data.deltaFrameFields = deltaFields;
|
||||
|
||||
size_t currentDeltaField = 0;
|
||||
for(size_t i = 0; i < pds->fieldSize; i++) {
|
||||
@ -473,8 +457,8 @@ UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_PubSubManager *psm,
|
||||
|
||||
UA_DataSetMessage_DeltaFrameField *dff = &deltaFields[currentDeltaField];
|
||||
|
||||
dff->fieldIndex = (UA_UInt16) i;
|
||||
UA_DataValue_copy(&dsw->lastSamples[i].value, &dff->fieldValue);
|
||||
dff->index = (UA_UInt16)i;
|
||||
UA_DataValue_copy(&dsw->lastSamples[i].value, &dff->value);
|
||||
|
||||
/* Reset the changed flag */
|
||||
dsw->lastSamples[i].valueChanged = false;
|
||||
@ -482,21 +466,21 @@ UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_PubSubManager *psm,
|
||||
/* Deactivate statuscode? */
|
||||
if(((u64)dsw->config.dataSetFieldContentMask &
|
||||
(u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0)
|
||||
dff->fieldValue.hasStatus = false;
|
||||
dff->value.hasStatus = false;
|
||||
|
||||
/* Deactivate timestamps? */
|
||||
if(((u64)dsw->config.dataSetFieldContentMask &
|
||||
(u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0)
|
||||
dff->fieldValue.hasSourceTimestamp = false;
|
||||
dff->value.hasSourceTimestamp = false;
|
||||
if(((u64)dsw->config.dataSetFieldContentMask &
|
||||
(u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0)
|
||||
dff->fieldValue.hasServerPicoseconds = false;
|
||||
dff->value.hasServerPicoseconds = false;
|
||||
if(((u64)dsw->config.dataSetFieldContentMask &
|
||||
(u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0)
|
||||
dff->fieldValue.hasServerTimestamp = false;
|
||||
dff->value.hasServerTimestamp = false;
|
||||
if(((u64)dsw->config.dataSetFieldContentMask &
|
||||
(u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0)
|
||||
dff->fieldValue.hasServerPicoseconds = false;
|
||||
dff->value.hasServerPicoseconds = false;
|
||||
|
||||
currentDeltaField++;
|
||||
}
|
||||
@ -562,9 +546,6 @@ UA_DataSetWriter_generateDataSetMessage(UA_PubSubManager *psm,
|
||||
// dsm->configuredSize = 0;
|
||||
}
|
||||
|
||||
/* setting configured size in the dataSetMessage to add padding later on */
|
||||
dataSetMessage->configuredSize = dsm->configuredSize;
|
||||
|
||||
/* Std: 'The DataSetMessageContentMask defines the flags for the content
|
||||
* of the DataSetMessage header.' */
|
||||
if((u64)dsm->dataSetMessageContentMask &
|
||||
@ -658,7 +639,7 @@ UA_DataSetWriter_generateDataSetMessage(UA_PubSubManager *psm,
|
||||
/* Prepare DataSetMessageContent for the heartbeat message */
|
||||
dataSetMessage->header.dataSetMessageValid = true;
|
||||
dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
|
||||
dataSetMessage->data.keyFrameData.fieldCount = 0;
|
||||
dataSetMessage->fieldCount = 0;
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
|
@ -574,24 +574,21 @@ encryptAndSign(UA_WriterGroup *wg, const UA_NetworkMessage *nm,
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
encodeNetworkMessage(UA_WriterGroup *wg, UA_NetworkMessage *nm,
|
||||
UA_ByteString *buf) {
|
||||
UA_Byte *bufPos = buf->data;
|
||||
UA_Byte *bufEnd = &buf->data[buf->length];
|
||||
|
||||
UA_Byte *networkMessageStart = bufPos;
|
||||
UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(nm, &bufPos, bufEnd);
|
||||
encodeNetworkMessage(UA_WriterGroup *wg, PubSubEncodeCtx *ctx,
|
||||
UA_NetworkMessage *nm, UA_ByteString *buf) {
|
||||
UA_Byte *networkMessageStart = buf->data;
|
||||
UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(ctx, nm);
|
||||
UA_CHECK_STATUS(rv, return rv);
|
||||
|
||||
UA_Byte *payloadStart = bufPos;
|
||||
rv = UA_NetworkMessage_encodePayload(nm, &bufPos, bufEnd);
|
||||
UA_Byte *payloadStart = ctx->ctx.pos;
|
||||
rv = UA_NetworkMessage_encodePayload(ctx, nm);
|
||||
UA_CHECK_STATUS(rv, return rv);
|
||||
|
||||
rv = UA_NetworkMessage_encodeFooters(nm, &bufPos, bufEnd);
|
||||
rv = UA_NetworkMessage_encodeFooters(ctx, nm);
|
||||
UA_CHECK_STATUS(rv, return rv);
|
||||
|
||||
/* Encrypt and Sign the message */
|
||||
UA_Byte *footerEnd = bufPos;
|
||||
UA_Byte *footerEnd = ctx->ctx.pos;
|
||||
return encryptAndSign(wg, nm, networkMessageStart, payloadStart, footerEnd);
|
||||
}
|
||||
|
||||
@ -634,8 +631,28 @@ sendNetworkMessageJson(UA_PubSubManager *psm, UA_PubSubConnection *connection, U
|
||||
for(size_t i = 0; i < dsmCount; i++)
|
||||
nm.payload.dataSetPayload.dataSetMessages[i].dataSetWriterId = writerIds[i];
|
||||
|
||||
PubSubEncodeJsonCtx ctx;
|
||||
memset(&ctx, 0, sizeof(PubSubEncodeJsonCtx));
|
||||
|
||||
/* Prepare the metadata to encode the DataSetMessages */
|
||||
size_t i = 0;
|
||||
UA_STACKARRAY(UA_DataSetMessage_EncodingMetaData, emd, wg->writersCount);
|
||||
memset(emd, 0, sizeof(UA_DataSetMessage_EncodingMetaData) * wg->writersCount);
|
||||
ctx.eo.metaData = emd;
|
||||
ctx.eo.metaDataSize = wg->writersCount;
|
||||
UA_DataSetWriter *dsw;
|
||||
LIST_FOREACH(dsw, &wg->writers, listEntry) {
|
||||
emd[i].dataSetWriterId = dsw->config.dataSetWriterId;
|
||||
UA_PublishedDataSet *pds = dsw->connectedDataSet;
|
||||
if(pds) {
|
||||
emd[i].fields = pds->dataSetMetaData.fields;
|
||||
emd[i].fieldsSize = pds->dataSetMetaData.fieldsSize;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Compute the message length */
|
||||
size_t msgSize = UA_NetworkMessage_calcSizeJsonInternal(&nm, NULL, NULL, 0, true);
|
||||
size_t msgSize = UA_NetworkMessage_calcSizeJson(&nm, &ctx.eo, NULL);
|
||||
|
||||
UA_ConnectionManager *cm = connection->cm;
|
||||
if(!cm)
|
||||
@ -656,14 +673,14 @@ sendNetworkMessageJson(UA_PubSubManager *psm, UA_PubSubConnection *connection, U
|
||||
UA_CHECK_STATUS(res, return res);
|
||||
|
||||
/* Encode the message */
|
||||
UA_Byte *bufPos = buf.data;
|
||||
const UA_Byte *bufEnd = &buf.data[msgSize];
|
||||
res = UA_NetworkMessage_encodeJsonInternal(&nm, &bufPos, &bufEnd, NULL, NULL, 0, true);
|
||||
ctx.ctx.pos = buf.data;
|
||||
ctx.ctx.end = &buf.data[msgSize];
|
||||
res = UA_NetworkMessage_encodeJsonInternal(&ctx, &nm);
|
||||
if(res != UA_STATUSCODE_GOOD) {
|
||||
cm->freeNetworkBuffer(cm, sendChannel, &buf);
|
||||
return res;
|
||||
}
|
||||
UA_assert(bufPos == bufEnd);
|
||||
UA_assert(ctx.ctx.pos == ctx.ctx.end);
|
||||
|
||||
/* Send the prepared messages */
|
||||
sendNetworkMessageBuffer(psm, wg, connection, sendChannel, &buf);
|
||||
@ -782,9 +799,30 @@ sendNetworkMessageBinary(UA_PubSubManager *psm, UA_PubSubConnection *connection,
|
||||
&wg->config.transportSettings, &nm);
|
||||
UA_CHECK_STATUS(rv, return rv);
|
||||
|
||||
PubSubEncodeCtx ctx;
|
||||
memset(&ctx, 0, sizeof(PubSubEncodeCtx));
|
||||
|
||||
/* Prepare the metadata with information from the readers to decode the
|
||||
* DataSetMessages */
|
||||
size_t i = 0;
|
||||
UA_STACKARRAY(UA_DataSetMessage_EncodingMetaData, emd, wg->writersCount);
|
||||
memset(emd, 0, sizeof(UA_DataSetMessage_EncodingMetaData) * wg->writersCount);
|
||||
ctx.eo.metaData = emd;
|
||||
ctx.eo.metaDataSize = wg->writersCount;
|
||||
UA_DataSetWriter *dsw;
|
||||
LIST_FOREACH(dsw, &wg->writers, listEntry) {
|
||||
emd[i].dataSetWriterId = dsw->config.dataSetWriterId;
|
||||
UA_PublishedDataSet *pds = dsw->connectedDataSet;
|
||||
if(pds) {
|
||||
emd[i].fields = pds->dataSetMetaData.fields;
|
||||
emd[i].fieldsSize = pds->dataSetMetaData.fieldsSize;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Compute the message size. Add the overhead for the security signature.
|
||||
* There is no padding and the encryption incurs no size overhead. */
|
||||
size_t msgSize = UA_NetworkMessage_calcSizeBinary(&nm);
|
||||
size_t msgSize = UA_NetworkMessage_calcSizeBinary(&nm, &ctx.eo);
|
||||
if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) {
|
||||
UA_PubSubSecurityPolicy *sp = wg->config.securityPolicy;
|
||||
msgSize += sp->symmetricModule.cryptoModule.
|
||||
@ -810,7 +848,9 @@ sendNetworkMessageBinary(UA_PubSubManager *psm, UA_PubSubConnection *connection,
|
||||
UA_CHECK_STATUS(rv, return rv);
|
||||
|
||||
/* Encode and encrypt the message */
|
||||
rv = encodeNetworkMessage(wg, &nm, &buf);
|
||||
ctx.ctx.pos = buf.data;
|
||||
ctx.ctx.end = &buf.data[buf.length];
|
||||
rv = encodeNetworkMessage(wg, &ctx, &nm, &buf);
|
||||
if(rv != UA_STATUSCODE_GOOD) {
|
||||
cm->freeNetworkBuffer(cm, sendChannel, &buf);
|
||||
return rv;
|
||||
@ -1514,10 +1554,30 @@ UA_Server_computeWriterGroupOffsetTable(UA_Server *server,
|
||||
memset(&networkMessage, 0, sizeof(networkMessage));
|
||||
memset(ot, 0, sizeof(UA_PubSubOffsetTable));
|
||||
|
||||
/* Prepare the metadata encode the DataSetMessages */
|
||||
PubSubEncodeCtx ctx;
|
||||
memset(&ctx, 0, sizeof(PubSubEncodeCtx));
|
||||
ctx.ot = ot;
|
||||
|
||||
size_t i = 0;
|
||||
UA_STACKARRAY(UA_DataSetMessage_EncodingMetaData, emd, wg->writersCount);
|
||||
memset(emd, 0, sizeof(UA_DataSetMessage_EncodingMetaData) * wg->writersCount);
|
||||
ctx.eo.metaData = emd;
|
||||
ctx.eo.metaDataSize = wg->writersCount;
|
||||
UA_DataSetWriter *dsw;
|
||||
LIST_FOREACH(dsw, &wg->writers, listEntry) {
|
||||
emd[i].dataSetWriterId = dsw->config.dataSetWriterId;
|
||||
UA_PublishedDataSet *pds = dsw->connectedDataSet;
|
||||
if(pds) {
|
||||
emd[i].fields = pds->dataSetMetaData.fields;
|
||||
emd[i].fieldsSize = pds->dataSetMetaData.fieldsSize;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Validate the DataSetWriters and generate their DataSetMessage */
|
||||
size_t msgSize;
|
||||
size_t dsmCount = 0;
|
||||
UA_DataSetWriter *dsw;
|
||||
UA_StatusCode res = UA_STATUSCODE_GOOD;
|
||||
UA_STACKARRAY(UA_UInt16, dsWriterIds, wg->writersCount);
|
||||
UA_STACKARRAY(UA_DataSetMessage, dsmStore, wg->writersCount);
|
||||
@ -1539,14 +1599,14 @@ UA_Server_computeWriterGroupOffsetTable(UA_Server *server,
|
||||
|
||||
/* Compute the message length and generate the old format offset-table (done
|
||||
* inside calcSizeBinary) */
|
||||
msgSize = UA_NetworkMessage_calcSizeBinaryWithOffsetTable(&networkMessage, ot);
|
||||
msgSize = UA_NetworkMessage_calcSizeBinaryInternal(&ctx, &networkMessage);
|
||||
if(msgSize == 0) {
|
||||
res = UA_STATUSCODE_BADINTERNALERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Create the encoded network message */
|
||||
res = UA_NetworkMessage_encodeBinary(&networkMessage, &ot->networkMessage);
|
||||
res = UA_NetworkMessage_encodeBinary(&networkMessage, &ot->networkMessage, &ctx.eo);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
goto cleanup;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -8,14 +8,27 @@
|
||||
#include <open62541/client.h>
|
||||
#include <open62541/types.h>
|
||||
#include <open62541/util.h>
|
||||
|
||||
#include "ua_pubsub_networkmessage.h"
|
||||
#include <open62541/pubsub.h>
|
||||
|
||||
#include <check.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
START_TEST(UA_PubSub_EncodeAllOptionalFields) {
|
||||
UA_UInt16 dsWriter1 = 12345;
|
||||
|
||||
/* Set up the metadata for decoding */
|
||||
UA_NetworkMessage_EncodingOptions eo = {0};
|
||||
UA_DataSetMessage_EncodingMetaData emd[1] = {0};
|
||||
UA_FieldMetaData fmd[1] = {0};
|
||||
fmd[0].name = UA_STRING("Field1");
|
||||
|
||||
eo.metaData = emd;
|
||||
eo.metaDataSize = 1;
|
||||
|
||||
emd[0].dataSetWriterId = dsWriter1;
|
||||
emd[0].fields = fmd;
|
||||
emd[0].fieldsSize = 1;
|
||||
|
||||
UA_NetworkMessage m;
|
||||
memset(&m, 0, sizeof(UA_NetworkMessage));
|
||||
m.version = 1;
|
||||
@ -41,58 +54,50 @@ START_TEST(UA_PubSub_EncodeAllOptionalFields) {
|
||||
m.dataSetClassId.data2 = 2;
|
||||
m.dataSetClassId.data3 = 3;
|
||||
|
||||
UA_DataSetMessage *dsm = m.payload.dataSetPayload.dataSetMessages;
|
||||
|
||||
/* DatasetMessage */
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageValid = true;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.fieldEncoding = UA_FIELDENCODING_VARIANT;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
|
||||
dsm->header.dataSetMessageValid = true;
|
||||
dsm->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
|
||||
dsm->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
|
||||
UA_UInt16 fieldCountDS1 = 1;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldCount = fieldCountDS1;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields =
|
||||
(UA_DataValue*)UA_Array_new(m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
|
||||
UA_DataValue_init(&m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0]);
|
||||
dsm->fieldCount = fieldCountDS1;
|
||||
dsm->data.keyFrameFields = UA_DataValue_new();
|
||||
|
||||
/* enable DataSetMessageSequenceNr */
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageSequenceNrEnabled = true;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageSequenceNr = 4711;
|
||||
dsm->header.dataSetMessageSequenceNrEnabled = true;
|
||||
dsm->header.dataSetMessageSequenceNr = 4711;
|
||||
|
||||
/* enable metaDataVersion */
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.configVersionMajorVersionEnabled = true;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.configVersionMinorVersionEnabled = true;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.configVersionMajorVersion = 42;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.configVersionMinorVersion = 7;
|
||||
dsm->header.configVersionMajorVersionEnabled = true;
|
||||
dsm->header.configVersionMinorVersionEnabled = true;
|
||||
dsm->header.configVersionMajorVersion = 42;
|
||||
dsm->header.configVersionMinorVersion = 7;
|
||||
|
||||
/* enable timestamp */
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.timestampEnabled = true;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.timestamp = 11111111111111;
|
||||
dsm->header.timestampEnabled = true;
|
||||
dsm->header.timestamp = 11111111111111;
|
||||
|
||||
/* enable status */
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.statusEnabled = true;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.status = 12345;
|
||||
|
||||
/* Set fieldnames */
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames =
|
||||
(UA_String*)UA_Array_new(m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_STRING]);
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[0] = UA_STRING_ALLOC("Field1");
|
||||
dsm->header.statusEnabled = true;
|
||||
dsm->header.status = 12345;
|
||||
|
||||
UA_UInt32 iv = 27;
|
||||
UA_Variant_setScalarCopy(&m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].value, &iv, &UA_TYPES[UA_TYPES_UINT32]);
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].hasValue = true;
|
||||
UA_Variant_setScalarCopy(&dsm->data.keyFrameFields[0].value,
|
||||
&iv, &UA_TYPES[UA_TYPES_UINT32]);
|
||||
dsm->data.keyFrameFields[0].hasValue = true;
|
||||
|
||||
size_t size = UA_NetworkMessage_calcSizeJsonInternal(&m, NULL, NULL, 0, true);
|
||||
size_t size = UA_NetworkMessage_calcSizeJson(&m, &eo, NULL);
|
||||
|
||||
UA_ByteString buffer;
|
||||
UA_ByteString buffer = UA_BYTESTRING_NULL;
|
||||
UA_StatusCode rv = UA_ByteString_allocBuffer(&buffer, size+1);
|
||||
ck_assert_int_eq(rv, UA_STATUSCODE_GOOD);
|
||||
memset(buffer.data, 0, size+1);
|
||||
|
||||
UA_Byte *bufPos = buffer.data;
|
||||
memset(bufPos, 0, size+1);
|
||||
const UA_Byte *bufEnd = &(buffer.data[buffer.length]);
|
||||
|
||||
rv = UA_NetworkMessage_encodeJsonInternal(&m, &bufPos, &bufEnd, NULL, NULL, 0, true);
|
||||
*bufPos = 0;
|
||||
// then
|
||||
rv = UA_NetworkMessage_encodeJson(&m, &buffer, &eo, NULL);
|
||||
ck_assert_int_eq(rv, UA_STATUSCODE_GOOD);
|
||||
|
||||
// then
|
||||
char* result = "{\"MessageId\":\"ABCDEFGH\",\"MessageType\":\"ua-data\",\"PublisherId\":\"65535\",\"DataSetClassId\":\"00000001-0002-0003-0000-000000000000\",\"Messages\":[{\"DataSetWriterId\":12345,\"SequenceNumber\":4711,\"MetaDataVersion\":{\"MajorVersion\":42,\"MinorVersion\":7},\"Timestamp\":\"1601-01-13T20:38:31.1111111Z\",\"Status\":12345,\"MessageType\":\"ua-keyframe\",\"Payload\":{\"Field1\":{\"UaType\":7,\"Value\":27}}}]}";
|
||||
ck_assert_str_eq(result, (char*)buffer.data);
|
||||
|
||||
@ -104,6 +109,27 @@ END_TEST
|
||||
START_TEST(UA_PubSub_EnDecode) {
|
||||
UA_UInt16 dsWriter1 = 4;
|
||||
UA_UInt16 dsWriter2 = 7;
|
||||
|
||||
/* Set up the metadata for decoding */
|
||||
UA_NetworkMessage_EncodingOptions eo = {0};
|
||||
UA_DataSetMessage_EncodingMetaData emd[2]= {0};
|
||||
UA_FieldMetaData fmd0[1] = {0};
|
||||
UA_FieldMetaData fmd1[2] = {0};
|
||||
|
||||
fmd0[0].name = UA_STRING("Field1");
|
||||
emd[0].fields = fmd0;
|
||||
emd[0].fieldsSize = 1;
|
||||
emd[0].dataSetWriterId = dsWriter1;
|
||||
|
||||
fmd1[0].name = UA_STRING("Field2.1");
|
||||
fmd1[0].name = UA_STRING("Field2.2");
|
||||
emd[1].fields = fmd1;
|
||||
emd[1].fieldsSize = 2;
|
||||
emd[1].dataSetWriterId = dsWriter2;
|
||||
|
||||
eo.metaData = emd;
|
||||
eo.metaDataSize = 2;
|
||||
|
||||
UA_NetworkMessage m;
|
||||
memset(&m, 0, sizeof(UA_NetworkMessage));
|
||||
m.version = 1;
|
||||
@ -112,68 +138,57 @@ START_TEST(UA_PubSub_EnDecode) {
|
||||
m.payload.dataSetPayload.dataSetMessages = (UA_DataSetMessage*)
|
||||
UA_calloc(2, sizeof(UA_DataSetMessage));
|
||||
m.payload.dataSetPayload.dataSetMessagesSize = 2;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].dataSetWriterId = dsWriter1;
|
||||
m.payload.dataSetPayload.dataSetMessages[1].dataSetWriterId = dsWriter2;
|
||||
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageValid = true;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.fieldEncoding = UA_FIELDENCODING_VARIANT;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
|
||||
UA_DataSetMessage *dsm0 = &m.payload.dataSetPayload.dataSetMessages[0];
|
||||
UA_DataSetMessage *dsm1 = &m.payload.dataSetPayload.dataSetMessages[1];
|
||||
|
||||
dsm0->dataSetWriterId = dsWriter1;
|
||||
dsm1->dataSetWriterId = dsWriter2;
|
||||
|
||||
dsm0->header.dataSetMessageValid = true;
|
||||
dsm0->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
|
||||
dsm0->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
|
||||
UA_UInt16 fieldCountDS1 = 1;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldCount = fieldCountDS1;
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields =
|
||||
(UA_DataValue*)UA_Array_new(m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
|
||||
UA_DataValue_init(&m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0]);
|
||||
|
||||
/* Set fieldnames */
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames =
|
||||
(UA_String*)UA_Array_new(m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_STRING]);
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[0] = UA_STRING_ALLOC("Field1");
|
||||
dsm0->fieldCount = fieldCountDS1;
|
||||
dsm0->data.keyFrameFields = UA_DataValue_new();
|
||||
|
||||
UA_UInt32 iv = 27;
|
||||
UA_Variant_setScalarCopy(&m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].value, &iv, &UA_TYPES[UA_TYPES_UINT32]);
|
||||
m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].hasValue = true;
|
||||
UA_Variant_setScalarCopy(&dsm0->data.keyFrameFields[0].value, &iv, &UA_TYPES[UA_TYPES_UINT32]);
|
||||
dsm0->data.keyFrameFields[0].hasValue = true;
|
||||
|
||||
m.payload.dataSetPayload.dataSetMessages[1].header.dataSetMessageValid = true;
|
||||
m.payload.dataSetPayload.dataSetMessages[1].header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
|
||||
m.payload.dataSetPayload.dataSetMessages[1].header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
|
||||
dsm1->header.dataSetMessageValid = true;
|
||||
dsm1->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
|
||||
dsm1->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
|
||||
UA_UInt16 fieldCountDS2 = 2;
|
||||
m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.fieldCount = fieldCountDS2;
|
||||
m.payload.dataSetPayload.dataSetMessages[1].data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)
|
||||
UA_calloc(m.payload.dataSetPayload.dataSetMessages[1].data.deltaFrameData.fieldCount, sizeof(UA_DataSetMessage_DeltaFrameField));
|
||||
/* Set fieldnames */
|
||||
m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.fieldNames =
|
||||
(UA_String*)UA_Array_new(m.payload.dataSetPayload.dataSetMessages[1].data.deltaFrameData.fieldCount, &UA_TYPES[UA_TYPES_STRING]);
|
||||
m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.fieldNames[0] = UA_STRING_ALLOC("Field2.1");
|
||||
m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.fieldNames[1] = UA_STRING_ALLOC("Field2.2");
|
||||
dsm1->fieldCount = fieldCountDS2;
|
||||
dsm1->data.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)
|
||||
UA_calloc(dsm1->fieldCount, sizeof(UA_DataSetMessage_DeltaFrameField));
|
||||
|
||||
UA_Guid gv = UA_Guid_random();
|
||||
UA_DataValue_init(&m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.dataSetFields[0]);
|
||||
UA_Variant_setScalarCopy(&m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.dataSetFields[0].value, &gv, &UA_TYPES[UA_TYPES_GUID]);
|
||||
m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.dataSetFields[0].hasValue = true;
|
||||
UA_DataValue_init(&dsm1->data.keyFrameFields[0]);
|
||||
UA_Variant_setScalarCopy(&dsm1->data.keyFrameFields[0].value, &gv, &UA_TYPES[UA_TYPES_GUID]);
|
||||
dsm1->data.keyFrameFields[0].hasValue = true;
|
||||
|
||||
UA_DataValue_init(&m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.dataSetFields[1]);
|
||||
UA_DataValue_init(&dsm1->data.keyFrameFields[1]);
|
||||
UA_Int64 iv64 = 152478978534;
|
||||
UA_Variant_setScalarCopy(&m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.dataSetFields[1].value, &iv64, &UA_TYPES[UA_TYPES_INT64]);
|
||||
m.payload.dataSetPayload.dataSetMessages[1].data.keyFrameData.dataSetFields[1].hasValue = true;
|
||||
UA_Variant_setScalarCopy(&dsm1->data.keyFrameFields[1].value, &iv64, &UA_TYPES[UA_TYPES_INT64]);
|
||||
dsm1->data.keyFrameFields[1].hasValue = true;
|
||||
|
||||
size_t size = UA_NetworkMessage_calcSizeJsonInternal(&m, NULL, NULL, 0, true);
|
||||
size_t size = UA_NetworkMessage_calcSizeJson(&m, &eo, NULL);
|
||||
|
||||
UA_ByteString buffer;
|
||||
UA_StatusCode rv = UA_ByteString_allocBuffer(&buffer, size);
|
||||
UA_StatusCode rv = UA_ByteString_allocBuffer(&buffer, size+1);
|
||||
ck_assert_int_eq(rv, UA_STATUSCODE_GOOD);
|
||||
memset(buffer.data, 0, size+1);
|
||||
|
||||
rv = UA_NetworkMessage_encodeJson(&m, &buffer, &eo, NULL);
|
||||
ck_assert_int_eq(rv, UA_STATUSCODE_GOOD);
|
||||
|
||||
UA_Byte *bufPos = buffer.data;
|
||||
memset(bufPos, 0, size);
|
||||
const UA_Byte *bufEnd = &(buffer.data[buffer.length]);
|
||||
|
||||
rv = UA_NetworkMessage_encodeJsonInternal(&m, &bufPos, &bufEnd, NULL, NULL, 0, true);
|
||||
//*bufPos = 0;
|
||||
// then
|
||||
ck_assert_int_eq(rv, UA_STATUSCODE_GOOD);
|
||||
|
||||
UA_NetworkMessage m2;
|
||||
memset(&m2, 0, sizeof(UA_NetworkMessage));
|
||||
rv = UA_NetworkMessage_decodeJson(&buffer, &m2, NULL);
|
||||
rv = UA_NetworkMessage_decodeJson(&buffer, &m2, &eo, NULL);
|
||||
ck_assert_int_eq(rv, UA_STATUSCODE_GOOD);
|
||||
ck_assert(m.networkMessageType == m2.networkMessageType);
|
||||
ck_assert(m.timestampEnabled == m2.timestampEnabled);
|
||||
@ -189,14 +204,14 @@ START_TEST(UA_PubSub_EnDecode) {
|
||||
ck_assert_uint_eq(m2.payload.dataSetPayload.dataSetMessages[1].dataSetWriterId, dsWriter2);
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageValid == m2.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageValid);
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[0].header.fieldEncoding == m2.payload.dataSetPayload.dataSetMessages[0].header.fieldEncoding);
|
||||
ck_assert_int_eq(m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldCount, fieldCountDS1);
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].hasValue == m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].hasValue);
|
||||
ck_assert_uint_eq((uintptr_t)m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].value.type, (uintptr_t)&UA_TYPES[UA_TYPES_UINT32]);
|
||||
ck_assert_uint_eq(*(UA_UInt32 *)m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].value.data, iv);
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].hasSourceTimestamp == m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].hasSourceTimestamp);
|
||||
ck_assert_int_eq(m2.payload.dataSetPayload.dataSetMessages[0].fieldCount, fieldCountDS1);
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].hasValue == m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].hasValue);
|
||||
ck_assert_uint_eq((uintptr_t)m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].value.type, (uintptr_t)&UA_TYPES[UA_TYPES_UINT32]);
|
||||
ck_assert_uint_eq(*(UA_UInt32 *)m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].value.data, iv);
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].hasSourceTimestamp == m2.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].hasSourceTimestamp);
|
||||
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[1].header.dataSetMessageValid == m2.payload.dataSetPayload.dataSetMessages[1].header.dataSetMessageValid);
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[1].data.deltaFrameData.deltaFrameFields[0].fieldValue.hasSourceTimestamp == m2.payload.dataSetPayload.dataSetMessages[1].data.deltaFrameData.deltaFrameFields[0].fieldValue.hasSourceTimestamp);
|
||||
ck_assert(m.payload.dataSetPayload.dataSetMessages[1].data.deltaFrameFields[0].value.hasSourceTimestamp == m2.payload.dataSetPayload.dataSetMessages[1].data.deltaFrameFields[0].value.hasSourceTimestamp);
|
||||
UA_ByteString_clear(&buffer);
|
||||
UA_NetworkMessage_clear(&m);
|
||||
UA_NetworkMessage_clear(&m2);
|
||||
@ -205,12 +220,23 @@ END_TEST
|
||||
|
||||
|
||||
START_TEST(UA_NetworkMessage_oneMessage_twoFields_json_decode) {
|
||||
// given
|
||||
/* Set up the metadata for decoding */
|
||||
UA_NetworkMessage_EncodingOptions eo = {0};
|
||||
UA_DataSetMessage_EncodingMetaData emd[1]= {0};
|
||||
UA_FieldMetaData fmd[2] = {0};
|
||||
|
||||
fmd[0].name = UA_STRING("Test");
|
||||
fmd[1].name = UA_STRING("Server localtime");
|
||||
emd[0].fields = fmd;
|
||||
emd[0].fieldsSize = 2;
|
||||
emd[0].dataSetWriterId = 62541;
|
||||
|
||||
eo.metaData = emd;
|
||||
eo.metaDataSize = 2;
|
||||
|
||||
UA_NetworkMessage out;
|
||||
UA_ByteString buf = UA_STRING("{\"MessageId\":\"5ED82C10-50BB-CD07-0120-22521081E8EE\",\"MessageType\":\"ua-data\",\"Messages\":[{\"DataSetWriterId\":62541,\"MetaDataVersion\":{\"MajorVersion\":1478393530,\"MinorVersion\":12345},\"SequenceNumber\":4711,\"Payload\":{\"Test\":{\"UaType\":5,\"Value\":42},\"Server localtime\":{\"UaType\":13,\"Value\":\"2018-06-05T05:58:36.000Z\"}}}]}");
|
||||
// when
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, NULL);
|
||||
// then
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, &eo, NULL);
|
||||
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
//NetworkMessage
|
||||
@ -244,10 +270,10 @@ START_TEST(UA_NetworkMessage_oneMessage_twoFields_json_decode) {
|
||||
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].header.dataSetMessageSequenceNr, 4711);
|
||||
//ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].header.dataSetWriterId, 62541);
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].hasValue, 1);
|
||||
ck_assert_int_eq(*((UA_UInt16*)out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].value.data), 42);
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[1].hasValue, 1);
|
||||
UA_DateTime *dt = (UA_DateTime*)out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[1].value.data;
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].hasValue, 1);
|
||||
ck_assert_int_eq(*((UA_UInt16*)out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].value.data), 42);
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[1].hasValue, 1);
|
||||
UA_DateTime *dt = (UA_DateTime*)out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[1].value.data;
|
||||
UA_DateTimeStruct dts = UA_DateTime_toStruct(*dt);
|
||||
ck_assert_int_eq(dts.year, 2018);
|
||||
ck_assert_int_eq(dts.month, 6);
|
||||
@ -264,13 +290,15 @@ START_TEST(UA_NetworkMessage_oneMessage_twoFields_json_decode) {
|
||||
END_TEST
|
||||
|
||||
|
||||
// Decode without metadata
|
||||
// The values still come out in order
|
||||
START_TEST(UA_NetworkMessage_json_decode) {
|
||||
// given
|
||||
UA_NetworkMessage out;
|
||||
memset(&out,0,sizeof(UA_NetworkMessage));
|
||||
UA_ByteString buf = UA_STRING("{\"MessageId\":\"5ED82C10-50BB-CD07-0120-22521081E8EE\",\"MessageType\":\"ua-data\",\"Messages\":[{\"MetaDataVersion\":{\"MajorVersion\": 47, \"MinorVersion\": 47},\"DataSetWriterId\":62541,\"Status\":22,\"SequenceNumber\":4711,\"Payload\":{\"Test\":{\"UaType\":5,\"Value\":42},\"Server localtime\":{\"UaType\":1,\"Value\":true}}}]}");
|
||||
// when
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, NULL);
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, NULL, NULL);
|
||||
// then
|
||||
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
@ -307,10 +335,10 @@ START_TEST(UA_NetworkMessage_json_decode) {
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].header.configVersionMajorVersion, 47);
|
||||
|
||||
//dataSetFields
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].hasValue, true);
|
||||
ck_assert_int_eq(*((UA_UInt16*)out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[0].value.data), 42);
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[1].hasValue, true);
|
||||
ck_assert_int_eq(*((UA_Boolean*)out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.dataSetFields[1].value.data), 1);
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].hasValue, true);
|
||||
ck_assert_int_eq(*((UA_UInt16*)out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[0].value.data), 42);
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[1].hasValue, true);
|
||||
ck_assert_int_eq(*((UA_Boolean*)out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameFields[1].value.data), 1);
|
||||
|
||||
UA_NetworkMessage_clear(&out);
|
||||
}
|
||||
@ -323,7 +351,7 @@ START_TEST(UA_NetworkMessage_json_decode_messageObject) {
|
||||
memset(&out,0,sizeof(UA_NetworkMessage));
|
||||
UA_ByteString buf = UA_STRING("{\"MessageId\":\"5ED82C10-50BB-CD07-0120-22521081E8EE\",\"MessageType\":\"ua-data\",\"Messages\":{\"MetaDataVersion\":{\"MajorVersion\": 47, \"MinorVersion\": 47},\"DataSetWriterId\":62541,\"Status\":22,\"SequenceNumber\":4711,\"Payload\":{\"Test\":{\"UaType\":5,\"Value\":42},\"Server localtime\":{\"UaType\":1,\"Value\":true}}}}");
|
||||
// when
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, NULL);
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, NULL, NULL);
|
||||
// then
|
||||
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
|
||||
UA_NetworkMessage_clear(&out);
|
||||
@ -340,47 +368,18 @@ START_TEST(UA_Networkmessage_DataSetFieldsNull_json_decode) {
|
||||
"[ { \"DataSetWriterId\": 1, \"SequenceNumber\": 224, \"MetaDataVersion\": "
|
||||
"{ \"MajorVersion\": 1, \"MinorVersion\": 1 },\"Payload\":null}]}");
|
||||
// when
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, NULL);
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, NULL, NULL);
|
||||
// then
|
||||
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
|
||||
ck_assert_int_eq(out.dataSetClassId.data1, 5);
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages->header.dataSetMessageSequenceNr, 224);
|
||||
ck_assert_ptr_eq(out.payload.dataSetPayload.dataSetMessages->data.keyFrameData.dataSetFields, NULL);
|
||||
ck_assert_ptr_eq(out.payload.dataSetPayload.dataSetMessages->data.keyFrameFields, NULL);
|
||||
|
||||
UA_NetworkMessage_clear(&out);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST(UA_NetworkMessage_fieldNames_json_decode) {
|
||||
// given
|
||||
UA_NetworkMessage out;
|
||||
UA_ByteString buf = UA_STRING("{\"MessageId\":\"5ED82C10-50BB-CD07-0120-22521081E8EE\","
|
||||
"\"MessageType\":\"ua-data\",\"Messages\":"
|
||||
"[{\"DataSetWriterId\":62541,\"MetaDataVersion\":"
|
||||
"{\"MajorVersion\":1478393530,\"MinorVersion\":12345},"
|
||||
"\"SequenceNumber\":4711,\"Payload\":{\"Test\":{\"UaType\":5,\"Value\":42},\"Test2\":"
|
||||
"{\"UaType\":13,\"Value\":\"2018-06-05T05:58:36.000Z\"}}}]}");
|
||||
// when
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(&buf, &out, NULL);
|
||||
// then
|
||||
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
//NetworkMessage
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[0].data[0], 'T');
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[0].data[1], 'e');
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[0].data[2], 's');
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[0].data[3], 't');
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[1].data[0], 'T');
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[1].data[1], 'e');
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[1].data[2], 's');
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[1].data[3], 't');
|
||||
ck_assert_int_eq(out.payload.dataSetPayload.dataSetMessages[0].data.keyFrameData.fieldNames[1].data[4], '2');
|
||||
|
||||
UA_NetworkMessage_clear(&out);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *testSuite_networkmessage(void) {
|
||||
Suite *s = suite_create("Built-in Data Types 62541-6 Json");
|
||||
TCase *tc_json_networkmessage = tcase_create("networkmessage_json");
|
||||
@ -391,7 +390,6 @@ static Suite *testSuite_networkmessage(void) {
|
||||
tcase_add_test(tc_json_networkmessage, UA_NetworkMessage_json_decode);
|
||||
tcase_add_test(tc_json_networkmessage, UA_NetworkMessage_json_decode_messageObject);
|
||||
tcase_add_test(tc_json_networkmessage, UA_Networkmessage_DataSetFieldsNull_json_decode);
|
||||
tcase_add_test(tc_json_networkmessage, UA_NetworkMessage_fieldNames_json_decode);
|
||||
|
||||
suite_add_tcase(s, tc_json_networkmessage);
|
||||
return s;
|
||||
|
@ -65,18 +65,18 @@ encodeNetworkMessage(const UA_ByteString *buf, UA_ByteString *out) {
|
||||
options.useReversible = true;
|
||||
|
||||
UA_NetworkMessage msg;
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeBinary(buf, &msg, NULL);
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeBinary(buf, &msg, NULL, NULL);
|
||||
if(retval != UA_STATUSCODE_GOOD)
|
||||
return retval;
|
||||
|
||||
size_t jsonLength = UA_NetworkMessage_calcSizeJson(&msg, &options);
|
||||
size_t jsonLength = UA_NetworkMessage_calcSizeJson(&msg, NULL, &options);
|
||||
retval = UA_ByteString_allocBuffer(out, jsonLength);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_NetworkMessage_clear(&msg);
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = UA_NetworkMessage_encodeJson(&msg, out, &options);
|
||||
retval = UA_NetworkMessage_encodeJson(&msg, out, NULL, &options);
|
||||
UA_NetworkMessage_clear(&msg);
|
||||
if(retval != UA_STATUSCODE_GOOD)
|
||||
UA_ByteString_clear(out);
|
||||
@ -87,18 +87,18 @@ encodeNetworkMessage(const UA_ByteString *buf, UA_ByteString *out) {
|
||||
static UA_StatusCode
|
||||
decodeNetworkMessage(const UA_ByteString *buf, UA_ByteString *out) {
|
||||
UA_NetworkMessage msg;
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(buf, &msg, NULL);
|
||||
UA_StatusCode retval = UA_NetworkMessage_decodeJson(buf, &msg, NULL, NULL);
|
||||
if(retval != UA_STATUSCODE_GOOD)
|
||||
return retval;
|
||||
|
||||
size_t binLength = UA_NetworkMessage_calcSizeBinary(&msg);
|
||||
size_t binLength = UA_NetworkMessage_calcSizeBinary(&msg, NULL);
|
||||
retval = UA_ByteString_allocBuffer(out, binLength);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_NetworkMessage_clear(&msg);
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = UA_NetworkMessage_encodeBinary(&msg, out);
|
||||
retval = UA_NetworkMessage_encodeBinary(&msg, out, NULL);
|
||||
UA_NetworkMessage_clear(&msg);
|
||||
if(retval != UA_STATUSCODE_GOOD)
|
||||
UA_ByteString_clear(out);
|
||||
|
Loading…
Reference in New Issue
Block a user