refactor(pubsub): Use decoding Ctx structure directly

This commit is contained in:
Julius Pfrommer
2024-07-03 16:24:57 +02:00
committed by Julius Pfrommer
parent 5e23a43ab9
commit 6d923ff37d
9 changed files with 311 additions and 346 deletions
+5 -6
View File
@@ -574,8 +574,8 @@ UA_DataSetReader_create(UA_Server *server, UA_NodeId readerGroupIdentifier,
UA_NodeId *readerIdentifier);
UA_StatusCode
UA_DataSetReader_prepareOffsetBuffer(UA_Server *server, UA_DataSetReader *reader,
UA_ByteString *buf, size_t *pos);
UA_DataSetReader_prepareOffsetBuffer(Ctx *ctx, UA_DataSetReader *reader,
UA_ByteString *buf);
void
UA_DataSetReader_decodeAndProcessRT(UA_Server *server, UA_DataSetReader *dsr,
@@ -739,14 +739,13 @@ UA_ReaderGroup_process(UA_Server *server, UA_ReaderGroup *readerGroup,
#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
UA_StatusCode
verifyAndDecrypt(const UA_Logger *logger, UA_ByteString *buffer,
const size_t *currentPosition, const UA_NetworkMessage *nm,
verifyAndDecrypt(const UA_Logger *logger, Ctx *ctx, const UA_NetworkMessage *nm,
UA_Boolean doValidate, UA_Boolean doDecrypt,
void *channelContext, UA_PubSubSecurityPolicy *securityPolicy);
UA_StatusCode
verifyAndDecryptNetworkMessage(const UA_Logger *logger, UA_ByteString *buffer,
size_t *currentPosition, UA_NetworkMessage *nm,
verifyAndDecryptNetworkMessage(const UA_Logger *logger, Ctx *ctx,
UA_NetworkMessage *nm,
UA_ReaderGroup *readerGroup);
#endif
+13 -8
View File
@@ -26,7 +26,16 @@ decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos,
UA_dump_hex_pkg(buffer->data, buffer->length);
#endif
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(buffer, pos, nm);
/* Set up the decoding context */
Ctx ctx;
ctx.pos = buffer->data + (*pos);
ctx.end = buffer->data + buffer->length;
ctx.depth = 0;
memset(&ctx.opts, 0, sizeof(UA_DecodeBinaryOptions));
ctx.opts.customTypes = server->config.customDataTypes;
/* Decode the headers */
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(&ctx, nm);
if(rv != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING_CONNECTION(server->config.logging, connection,
"PubSub receive. decoding headers failed");
@@ -48,8 +57,7 @@ decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos,
if(retval != UA_STATUSCODE_GOOD)
continue;
processed = true;
rv = verifyAndDecryptNetworkMessage(server->config.logging, buffer, pos,
nm, readerGroup);
rv = verifyAndDecryptNetworkMessage(server->config.logging, &ctx, nm, readerGroup);
if(rv != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING_CONNECTION(server->config.logging, connection,
"Subscribe failed, verify and decrypt "
@@ -79,16 +87,13 @@ loops_exit:
}
#endif
UA_DecodeBinaryOptions opt;
memset(&opt, 0, sizeof(UA_DecodeBinaryOptions));
opt.customTypes = server->config.customDataTypes;
rv = UA_NetworkMessage_decodePayload(buffer, pos, nm, &opt);
rv = UA_NetworkMessage_decodePayload(&ctx, nm);
if(rv != UA_STATUSCODE_GOOD) {
UA_NetworkMessage_clear(nm);
return rv;
}
rv = UA_NetworkMessage_decodeFooters(buffer, pos, nm);
rv = UA_NetworkMessage_decodeFooters(&ctx, nm);
if(rv != UA_STATUSCODE_GOOD) {
UA_NetworkMessage_clear(nm);
return rv;
+217 -231
View File
@@ -14,6 +14,9 @@
#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
#define DECODE_BINARY(VAR, TYPE) \
decodeBinaryJumpTable[UA_DATATYPEKIND_##TYPE](ctx, VAR, NULL);
const UA_Byte NM_VERSION_MASK = 15;
const UA_Byte NM_PUBLISHER_ID_ENABLED_MASK = 16;
const UA_Byte NM_GROUP_HEADER_ENABLED_MASK = 32;
@@ -102,46 +105,46 @@ UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer) {
}
UA_StatusCode
UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
const UA_ByteString *src, size_t *bufferPosition) {
UA_NetworkMessage_updateBufferedNwMessage(Ctx *ctx, UA_NetworkMessageOffsetBuffer *buffer) {
/* The offset buffer was not prepared */
UA_NetworkMessage *nm = buffer->nm;
if(!nm)
return UA_STATUSCODE_BADINTERNALERROR;
/* The source string is too short */
if(src->length < buffer->buffer.length + *bufferPosition)
if((uintptr_t)(ctx->end - ctx->pos) < buffer->buffer.length)
return UA_STATUSCODE_BADDECODINGERROR;
/* If this remains at UA_UINT32_MAX, then no raw fields are contained */
size_t smallestRawOffset = UA_UINT32_MAX;
const UA_Byte *smallestRawOffset = ctx->end;
UA_Byte *initialPos = ctx->pos;
/* Considering one DSM in RT TODO: Clarify multiple DSM */
UA_DataSetMessage* dsm = nm->payload.dataSetPayload.dataSetMessages;
size_t pos = 0;
size_t payloadCounter = 0;
UA_DataSetMessageHeader header;
UA_StatusCode rv = UA_STATUSCODE_GOOD;
for(size_t i = 0; i < buffer->offsetsSize; ++i) {
pos = buffer->offsets[i].offset + *bufferPosition;
ctx->pos = initialPos + buffer->offsets[i].offset;
switch(buffer->offsets[i].contentType) {
case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING:
rv = UA_DataSetMessageHeader_decodeBinary(src, &pos, &header);
memset(&header, 0, sizeof(UA_DataSetMessageHeader));
rv = UA_DataSetMessageHeader_decodeBinary(ctx, &header);
break;
case UA_PUBSUB_OFFSETTYPE_PUBLISHERID:
switch(nm->publisherId.idType) {
case UA_PUBLISHERIDTYPE_BYTE:
rv = UA_Byte_decodeBinary(src, &pos, &nm->publisherId.id.byte);
rv = DECODE_BINARY(&nm->publisherId.id.byte, BYTE);
break;
case UA_PUBLISHERIDTYPE_UINT16:
rv = UA_UInt16_decodeBinary(src, &pos, &nm->publisherId.id.uint16);
rv = DECODE_BINARY(&nm->publisherId.id.uint16, UINT16);
break;
case UA_PUBLISHERIDTYPE_UINT32:
rv = UA_UInt32_decodeBinary(src, &pos, &nm->publisherId.id.uint32);
rv = DECODE_BINARY(&nm->publisherId.id.uint32, UINT32);
break;
case UA_PUBLISHERIDTYPE_UINT64:
rv = UA_UInt64_decodeBinary(src, &pos, &nm->publisherId.id.uint64);
rv = DECODE_BINARY(&nm->publisherId.id.uint64, UINT64);
break;
default:
/* UA_PUBLISHERIDTYPE_STRING is not supported because of
@@ -150,37 +153,34 @@ UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
}
break;
case UA_PUBSUB_OFFSETTYPE_WRITERGROUPID:
rv = UA_UInt16_decodeBinary(src, &pos, &nm->groupHeader.writerGroupId);
rv = DECODE_BINARY(&nm->groupHeader.writerGroupId, UINT16);
break;
case UA_PUBSUB_OFFSETTYPE_DATASETWRITERID:
rv = UA_UInt16_decodeBinary(src, &pos,
&nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]); /* TODO */
/* TODO */
rv = DECODE_BINARY(&nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0], UINT16);
break;
case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER:
rv = UA_UInt16_decodeBinary(src, &pos, &nm->groupHeader.sequenceNumber);
rv = DECODE_BINARY(&nm->groupHeader.sequenceNumber, UINT16);
break;
case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER:
rv = UA_UInt16_decodeBinary(src, &pos, &dsm->header.dataSetMessageSequenceNr);
rv = DECODE_BINARY(&dsm->header.dataSetMessageSequenceNr, UINT16);
break;
case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE:
UA_DataValue_clear(&dsm->data.keyFrameData.dataSetFields[payloadCounter]);
rv = UA_DataValue_decodeBinary(src, &pos,
&dsm->data.keyFrameData.dataSetFields[payloadCounter]);
rv = DECODE_BINARY(&dsm->data.keyFrameData.dataSetFields[payloadCounter], DATAVALUE);
payloadCounter++;
break;
case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT:
UA_Variant_clear(&dsm->data.keyFrameData.dataSetFields[payloadCounter].value);
rv = UA_Variant_decodeBinary(src, &pos,
&dsm->data.keyFrameData.dataSetFields[payloadCounter].value);
dsm->data.keyFrameData.dataSetFields[payloadCounter].hasValue =
(rv == UA_STATUSCODE_GOOD);
rv = DECODE_BINARY(&dsm->data.keyFrameData.dataSetFields[payloadCounter].value, VARIANT);
dsm->data.keyFrameData.dataSetFields[payloadCounter].hasValue = (rv == UA_STATUSCODE_GOOD);
payloadCounter++;
break;
case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW:
/* We need only the start address of the raw fields */
if(smallestRawOffset > pos){
smallestRawOffset = pos;
dsm->data.keyFrameData.rawFields.data = &src->data[pos];
if(smallestRawOffset > ctx->pos) {
smallestRawOffset = ctx->pos;
dsm->data.keyFrameData.rawFields.data = ctx->pos;
dsm->data.keyFrameData.rawFields.length = buffer->rawMessageLength;
}
payloadCounter++;
@@ -191,15 +191,6 @@ UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
UA_CHECK_STATUS(rv, return rv);
}
/* Check if the frame is of type "raw" payload. If yes, set the new buffer
* position to the start position of the raw fields plus the length of the
* raw fields. */
if(smallestRawOffset != UA_UINT32_MAX) {
*bufferPosition = smallestRawOffset + buffer->rawMessageLength;
} else {
*bufferPosition = pos;
}
return rv;
}
@@ -547,11 +538,10 @@ UA_NetworkMessage_encodeBinaryWithEncryptStart(const UA_NetworkMessage* src,
return rv;
}
UA_StatusCode
UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage *dst) {
UA_Byte decoded = 0;
UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
static UA_StatusCode
UA_NetworkMessageHeader_decodeBinary(Ctx *ctx, UA_NetworkMessage *dst) {
UA_Byte decoded;
UA_StatusCode rv = DECODE_BINARY(&decoded, BYTE);
UA_CHECK_STATUS(rv, return rv);
dst->version = decoded & NM_VERSION_MASK;
@@ -566,8 +556,7 @@ UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
dst->payloadHeaderEnabled = true;
if((decoded & NM_EXTENDEDFLAGS1_ENABLED_MASK) != 0) {
decoded = 0;
rv = UA_Byte_decodeBinary(src, offset, &decoded);
rv = DECODE_BINARY(&decoded, BYTE);
UA_CHECK_STATUS(rv, return rv);
dst->publisherId.idType = (UA_PublisherIdType)(decoded & NM_PUBLISHER_ID_MASK);
@@ -584,8 +573,7 @@ UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
dst->picosecondsEnabled = true;
if((decoded & NM_EXTENDEDFLAGS2_ENABLED_MASK) != 0) {
decoded = 0;
rv = UA_Byte_decodeBinary(src, offset, &decoded);
rv = DECODE_BINARY(&decoded, BYTE);
UA_CHECK_STATUS(rv, return rv);
if((decoded & NM_CHUNK_MESSAGE_MASK) != 0)
@@ -603,25 +591,20 @@ UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
if(dst->publisherIdEnabled) {
switch(dst->publisherId.idType) {
case UA_PUBLISHERIDTYPE_BYTE:
rv = UA_Byte_decodeBinary(src, offset, &dst->publisherId.id.byte);
rv = DECODE_BINARY(&dst->publisherId.id.byte, BYTE);
break;
case UA_PUBLISHERIDTYPE_UINT16:
rv = UA_UInt16_decodeBinary(src, offset, &dst->publisherId.id.uint16);
rv = DECODE_BINARY(&dst->publisherId.id.uint16, UINT16);
break;
case UA_PUBLISHERIDTYPE_UINT32:
rv = UA_UInt32_decodeBinary(src, offset, &dst->publisherId.id.uint32);
rv = DECODE_BINARY(&dst->publisherId.id.uint32, UINT32);
break;
case UA_PUBLISHERIDTYPE_UINT64:
rv = UA_UInt64_decodeBinary(src, offset, &dst->publisherId.id.uint64);
rv = DECODE_BINARY(&dst->publisherId.id.uint64, UINT64);
break;
case UA_PUBLISHERIDTYPE_STRING:
rv = UA_String_decodeBinary(src, offset, &dst->publisherId.id.string);
rv = DECODE_BINARY(&dst->publisherId.id.string, STRING);
break;
default:
rv = UA_STATUSCODE_BADINTERNALERROR;
break;
@@ -630,80 +613,78 @@ UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
}
if(dst->dataSetClassIdEnabled) {
rv = UA_Guid_decodeBinary(src, offset, &dst->dataSetClassId);
rv = DECODE_BINARY(&dst->dataSetClassId, GUID);
UA_CHECK_STATUS(rv, return rv);
}
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
UA_GroupHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage* dst) {
UA_Byte decoded = 0;
UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
UA_GroupHeader_decodeBinary(Ctx *ctx, UA_NetworkMessage* dst) {
UA_Byte decoded;
UA_StatusCode rv = DECODE_BINARY(&decoded, BYTE);
UA_CHECK_STATUS(rv, return rv);
if((decoded & GROUP_HEADER_WRITER_GROUPID_ENABLED) != 0) {
dst->groupHeader.writerGroupIdEnabled = true;
rv |= UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.writerGroupId);
rv |= DECODE_BINARY(&dst->groupHeader.writerGroupId, UINT16);
}
if((decoded & GROUP_HEADER_GROUP_VERSION_ENABLED) != 0) {
dst->groupHeader.groupVersionEnabled = true;
rv |= UA_UInt32_decodeBinary(src, offset, &dst->groupHeader.groupVersion);
rv |= DECODE_BINARY(&dst->groupHeader.groupVersion, UINT32);
}
if((decoded & GROUP_HEADER_NM_NUMBER_ENABLED) != 0) {
dst->groupHeader.networkMessageNumberEnabled = true;
rv |= UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.networkMessageNumber);
rv |= DECODE_BINARY(&dst->groupHeader.networkMessageNumber, UINT16);
}
if((decoded & GROUP_HEADER_SEQUENCE_NUMBER_ENABLED) != 0) {
dst->groupHeader.sequenceNumberEnabled = true;
rv |= UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.sequenceNumber);
rv |= DECODE_BINARY(&dst->groupHeader.sequenceNumber, UINT16);
}
return rv;
}
static UA_StatusCode
UA_PayloadHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage* dst) {
UA_PayloadHeader_decodeBinary(Ctx *ctx, UA_NetworkMessage* dst) {
if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
return UA_STATUSCODE_BADNOTIMPLEMENTED;
UA_DataSetPayloadHeader *h = &dst->payloadHeader.dataSetPayloadHeader;
UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &h->count);
UA_StatusCode rv = DECODE_BINARY(&h->count, BYTE);
UA_CHECK_STATUS(rv, return rv);
if(h->count == 0)
return UA_STATUSCODE_GOOD;
h->dataSetWriterIds = (UA_UInt16*)UA_Array_new(h->count, &UA_TYPES[UA_TYPES_UINT16]);
h->dataSetWriterIds = (UA_UInt16 *)ctxCalloc(ctx, h->count, sizeof(UA_UInt16));
if(!h->dataSetWriterIds) {
h->count = 0;
return UA_STATUSCODE_BADOUTOFMEMORY;
}
for(UA_Byte i = 0; i < h->count; i++) {
rv |= UA_UInt16_decodeBinary(src, offset, &h->dataSetWriterIds[i]);
rv |= DECODE_BINARY(&h->dataSetWriterIds[i], UINT16);
}
return rv;
}
static UA_StatusCode
UA_ExtendedNetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage* dst) {
UA_ExtendedNetworkMessageHeader_decodeBinary(Ctx *ctx, UA_NetworkMessage* dst) {
UA_StatusCode rv;
/* Timestamp*/
if(dst->timestampEnabled) {
rv = UA_DateTime_decodeBinary(src, offset, &dst->timestamp);
rv = DECODE_BINARY(&dst->timestamp, DATETIME);
UA_CHECK_STATUS(rv, return rv);
}
/* Picoseconds */
if(dst->picosecondsEnabled) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->picoseconds);
rv = DECODE_BINARY(&dst->picoseconds, UINT16);
UA_CHECK_STATUS(rv, return rv);
}
@@ -711,39 +692,61 @@ UA_ExtendedNetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *o
if(UA_LIKELY(!dst->promotedFieldsEnabled))
return UA_STATUSCODE_GOOD;
UA_UInt16 promotedFieldsSize = 0; /* Size in bytes, not in number of fields */
rv = UA_UInt16_decodeBinary(src, offset, &promotedFieldsSize);
UA_UInt16 promotedFieldsLength; /* Size in bytes, not in number of fields */
rv = DECODE_BINARY(&promotedFieldsLength, UINT16);
UA_CHECK_STATUS(rv, return rv);
if(promotedFieldsSize == 0)
if(promotedFieldsLength == 0)
return UA_STATUSCODE_GOOD;
size_t offsetEnd = (*offset) + promotedFieldsSize;
unsigned int counter = 0;
do {
UA_Variant *tmp = (UA_Variant*)
UA_realloc(dst->promotedFields, (size_t)
UA_TYPES[UA_TYPES_VARIANT].memSize * (counter + 1));
UA_CHECK_MEM(tmp, return UA_STATUSCODE_BADOUTOFMEMORY);
dst->promotedFields = tmp;
dst->promotedFieldsSize = (UA_UInt16) (counter + 1);
UA_Byte *endPos = ctx->pos + promotedFieldsLength;
if(endPos > ctx->end)
return UA_STATUSCODE_BADDECODINGERROR;
size_t counter = 0;
size_t space = 4;
UA_Variant *pf = (UA_Variant*)
ctxCalloc(ctx, space, UA_TYPES[UA_TYPES_VARIANT].memSize);
if(!pf)
return UA_STATUSCODE_BADOUTOFMEMORY;
UA_Variant_init(&dst->promotedFields[counter]);
rv = UA_Variant_decodeBinary(src, offset, &dst->promotedFields[counter]);
UA_CHECK_STATUS(rv, return rv);
do {
/* Increase the available space */
if(counter == space) {
UA_Variant *tmp = (UA_Variant*)
ctxCalloc(ctx, space << 1, UA_TYPES[UA_TYPES_VARIANT].memSize);
if(!tmp) {
if(!ctx->opts.calloc)
UA_Array_delete(pf, counter, &UA_TYPES[UA_TYPES_VARIANT]);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
memcpy(tmp, pf, space * UA_TYPES[UA_TYPES_VARIANT].memSize);
ctxFree(ctx, pf);
pf = tmp;
space = space << 1;
}
/* Decode the PromotedField */
rv = DECODE_BINARY(&pf[counter], VARIANT);
if(rv != UA_STATUSCODE_GOOD) {
if(!ctx->opts.calloc)
UA_Array_delete(pf, counter, &UA_TYPES[UA_TYPES_VARIANT]);
return rv;
}
counter++;
} while(*offset < offsetEnd);
} while(ctx->pos < endPos);
dst->promotedFields = pf;
dst->promotedFieldsSize = (UA_UInt16)counter;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
UA_SecurityHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage* dst) {
UA_Byte decoded = 0;
// SecurityFlags
decoded = 0;
UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
UA_SecurityHeader_decodeBinary(Ctx *ctx, UA_NetworkMessage* dst) {
/* SecurityFlags */
UA_Byte decoded;
UA_StatusCode rv = DECODE_BINARY(&decoded, BYTE);
UA_CHECK_STATUS(rv, return rv);
if((decoded & SECURITY_HEADER_NM_SIGNED) != 0)
@@ -758,64 +761,59 @@ UA_SecurityHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
if((decoded & SECURITY_HEADER_FORCE_KEY_RESET) != 0)
dst->securityHeader.forceKeyReset = true;
// SecurityTokenId
rv = UA_UInt32_decodeBinary(src, offset, &dst->securityHeader.securityTokenId);
/* SecurityTokenId */
rv = DECODE_BINARY(&dst->securityHeader.securityTokenId, UINT32);
UA_CHECK_STATUS(rv, return rv);
// MessageNonce
/* MessageNonce */
UA_Byte nonceLength;
rv = UA_Byte_decodeBinary(src, offset, &nonceLength);
rv = DECODE_BINARY(&nonceLength, BYTE);
UA_CHECK_STATUS(rv, return rv);
if(nonceLength > UA_NETWORKMESSAGE_MAX_NONCE_LENGTH)
return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
if(nonceLength > 0) {
dst->securityHeader.messageNonceSize = nonceLength;
for(UA_Byte i = 0; i < nonceLength; i++) {
rv = UA_Byte_decodeBinary(src, offset,
&dst->securityHeader.messageNonce[i]);
rv = DECODE_BINARY(&dst->securityHeader.messageNonce[i], BYTE);
UA_CHECK_STATUS(rv, return rv);
}
}
// SecurityFooterSize
if(dst->securityHeader.securityFooterEnabled) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->securityHeader.securityFooterSize);
UA_CHECK_STATUS(rv, return rv);
}
return UA_STATUSCODE_GOOD;
/* SecurityFooterSize */
if(dst->securityHeader.securityFooterEnabled)
rv = DECODE_BINARY(&dst->securityHeader.securityFooterSize, UINT16);
return rv;
}
UA_StatusCode
UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage *dst) {
UA_StatusCode rv = UA_NetworkMessageHeader_decodeBinary(src, offset, dst);
UA_NetworkMessage_decodeHeaders(Ctx *ctx, UA_NetworkMessage *dst) {
UA_StatusCode rv = UA_NetworkMessageHeader_decodeBinary(ctx, dst);
UA_CHECK_STATUS(rv, return rv);
if(dst->groupHeaderEnabled) {
rv = UA_GroupHeader_decodeBinary(src, offset, dst);
rv = UA_GroupHeader_decodeBinary(ctx, dst);
UA_CHECK_STATUS(rv, return rv);
}
if(dst->payloadHeaderEnabled) {
rv = UA_PayloadHeader_decodeBinary(src, offset, dst);
rv = UA_PayloadHeader_decodeBinary(ctx, dst);
UA_CHECK_STATUS(rv, return rv);
}
rv = UA_ExtendedNetworkMessageHeader_decodeBinary(src, offset, dst);
rv = UA_ExtendedNetworkMessageHeader_decodeBinary(ctx, dst);
UA_CHECK_STATUS(rv, return rv);
if(dst->securityEnabled) {
rv = UA_SecurityHeader_decodeBinary(src, offset, dst);
UA_CHECK_STATUS(rv, return rv);
}
if(dst->securityEnabled)
rv = UA_SecurityHeader_decodeBinary(ctx, dst);
return UA_STATUSCODE_GOOD;
return rv;
}
UA_StatusCode
UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst,
const UA_DecodeBinaryOptions *options) {
// Payload
UA_NetworkMessage_decodePayload(Ctx *ctx, UA_NetworkMessage *dst) {
/* Payload */
if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
return UA_STATUSCODE_BADNOTIMPLEMENTED;
@@ -829,9 +827,11 @@ UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_Net
return UA_STATUSCODE_BADDECODINGERROR;
if(count > 1) {
dst->payload.dataSetPayload.sizes = (UA_UInt16 *)
UA_Array_new(count, &UA_TYPES[UA_TYPES_UINT16]);
ctxCalloc(ctx, count, sizeof(UA_UInt16));
UA_CHECK_MEM(dst->payload.dataSetPayload.sizes,
return UA_STATUSCODE_BADOUTOFMEMORY);
for(UA_Byte i = 0; i < count; i++) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->payload.dataSetPayload.sizes[i]);
rv = DECODE_BINARY(&dst->payload.dataSetPayload.sizes[i], UINT16);
if(dst->payload.dataSetPayload.sizes[i] == 0)
return UA_STATUSCODE_BADDECODINGERROR;
UA_CHECK_STATUS(rv, return rv);
@@ -839,49 +839,39 @@ UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_Net
}
}
dst->payload.dataSetPayload.dataSetMessages = (UA_DataSetMessage*)
UA_calloc(count, sizeof(UA_DataSetMessage));
dst->payload.dataSetPayload.dataSetMessages =
(UA_DataSetMessage *)ctxCalloc(ctx, count, sizeof(UA_DataSetMessage));
UA_CHECK_MEM(dst->payload.dataSetPayload.dataSetMessages,
return UA_STATUSCODE_BADOUTOFMEMORY);
if(count == 1) {
rv = UA_DataSetMessage_decodeBinary(src, offset,
&dst->payload.dataSetPayload.dataSetMessages[0],
0, options);
rv = UA_DataSetMessage_decodeBinary(ctx, dst->payload.dataSetPayload.dataSetMessages, 0);
} else {
for(UA_Byte i = 0; i < count; i++) {
rv = UA_DataSetMessage_decodeBinary(src, offset,
rv = UA_DataSetMessage_decodeBinary(ctx,
&dst->payload.dataSetPayload.dataSetMessages[i],
dst->payload.dataSetPayload.sizes[i], options);
dst->payload.dataSetPayload.sizes[i]);
}
}
UA_CHECK_STATUS(rv, return rv);
return UA_STATUSCODE_GOOD;
/**
* TODO: check if making the cleanup to free its own allocated memory is better,
* currently the free happens in a parent context
*/
return rv;
}
UA_StatusCode
UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage *dst) {
UA_NetworkMessage_decodeFooters(Ctx *ctx, UA_NetworkMessage *dst) {
if(!dst->securityEnabled)
return UA_STATUSCODE_GOOD;
// SecurityFooter
UA_StatusCode rv = UA_STATUSCODE_GOOD;
if(dst->securityHeader.securityFooterEnabled &&
dst->securityHeader.securityFooterSize > 0) {
rv = UA_ByteString_allocBuffer(&dst->securityFooter,
dst->securityHeader.securityFooterSize);
UA_CHECK_STATUS(rv, return rv);
for(UA_UInt16 i = 0; i < dst->securityHeader.securityFooterSize; i++) {
rv |= UA_Byte_decodeBinary(src, offset, &dst->securityFooter.data[i]);
}
if(!dst->securityHeader.securityFooterEnabled ||
dst->securityHeader.securityFooterSize == 0)
return UA_STATUSCODE_GOOD;
UA_StatusCode rv = UA_ByteString_allocBuffer(&dst->securityFooter,
dst->securityHeader.securityFooterSize);
UA_CHECK_STATUS(rv, return rv);
for(UA_UInt16 i = 0; i < dst->securityHeader.securityFooterSize; i++) {
rv |= DECODE_BINARY(&dst->securityFooter.data[i], BYTE);
}
return rv;
}
@@ -889,14 +879,16 @@ UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset,
UA_StatusCode
UA_NetworkMessage_decodeBinary(const UA_ByteString *src, UA_NetworkMessage *dst,
const UA_DecodeBinaryOptions *options) {
size_t offset = 0;
return UA_NetworkMessage_decodeBinaryWithOffset(src, &offset, dst, options);
}
/* Initialize the decoding context */
Ctx ctx;
ctx.pos = src->data;
ctx.end = &src->data[src->length];
ctx.depth = 0;
if(options)
ctx.opts = *options;
else
memset(&ctx.opts, 0, sizeof(UA_DecodeBinaryOptions));
UA_StatusCode
UA_NetworkMessage_decodeBinaryWithOffset(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage* dst,
const UA_DecodeBinaryOptions *options) {
/* headers only need to be decoded when not in encryption mode
* because headers are already decoded when encryption mode is enabled
* to check for security parameters and decrypt/verify
@@ -911,16 +903,23 @@ UA_NetworkMessage_decodeBinaryWithOffset(const UA_ByteString *src, size_t *offse
// }
// #endif
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(src, offset, dst);
UA_CHECK_STATUS(rv, return rv);
/* Initialize the NetworkMessage */
memset(dst, 0, sizeof(UA_NetworkMessage));
rv = UA_NetworkMessage_decodePayload(src, offset, dst, options);
UA_CHECK_STATUS(rv, return rv);
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(&ctx, dst);
UA_CHECK_STATUS(rv, goto cleanup);
rv = UA_NetworkMessage_decodeFooters(src, offset, dst);
UA_CHECK_STATUS(rv, return rv);
rv = UA_NetworkMessage_decodePayload(&ctx, dst);
UA_CHECK_STATUS(rv, goto cleanup);
return UA_STATUSCODE_GOOD;
rv = UA_NetworkMessage_decodeFooters(&ctx, dst);
UA_CHECK_STATUS(rv, goto cleanup);
cleanup:
if(rv != UA_STATUSCODE_GOOD && !ctx.opts.calloc)
UA_NetworkMessage_clear(dst);
return rv;
}
static UA_Boolean
@@ -1285,11 +1284,9 @@ UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode secu
#endif
UA_StatusCode
UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_DataSetMessageHeader* dst) {
memset(dst, 0, sizeof(UA_DataSetMessageHeader));
UA_Byte v = 0;
UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &v);
UA_DataSetMessageHeader_decodeBinary(Ctx *ctx, UA_DataSetMessageHeader* dst) {
UA_Byte v;
UA_StatusCode rv = DECODE_BINARY(&v, BYTE);
UA_CHECK_STATUS(rv, return rv);
UA_Byte v2 = v & DS_MESSAGEHEADER_FIELD_ENCODING_MASK;
@@ -1312,8 +1309,7 @@ UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
dst->configVersionMinorVersionEnabled = true;
if((v & DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK) != 0) {
v = 0;
rv = UA_Byte_decodeBinary(src, offset, &v);
rv = DECODE_BINARY(&v, BYTE);
UA_CHECK_STATUS(rv, return rv);
dst->dataSetMessageType = (UA_DataSetMessageType)(v & DS_MESSAGEHEADER_DS_MESSAGE_TYPE_MASK);
@@ -1323,48 +1319,50 @@ UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
if((v & DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK) != 0)
dst->picoSecondsIncluded = true;
} else {
dst->dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
dst->picoSecondsIncluded = false;
}
/* The else-case is implied as dst is zeroed-out initially:
* else {
* dst->dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
* dst->picoSecondsIncluded = false;
* } */
if(dst->dataSetMessageSequenceNrEnabled) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->dataSetMessageSequenceNr);
rv = DECODE_BINARY(&dst->dataSetMessageSequenceNr, UINT16);
UA_CHECK_STATUS(rv, return rv);
} else {
dst->dataSetMessageSequenceNr = 0;
}
if(dst->timestampEnabled) {
rv = UA_DateTime_decodeBinary(src, offset, &dst->timestamp); /* UtcTime */
rv = DECODE_BINARY(&dst->timestamp, DATETIME);
UA_CHECK_STATUS(rv, return rv);
} else {
dst->timestamp = 0;
}
if(dst->picoSecondsIncluded) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->picoSeconds);
rv = DECODE_BINARY(&dst->picoSeconds, UINT16);
UA_CHECK_STATUS(rv, return rv);
} else {
dst->picoSeconds = 0;
}
if(dst->statusEnabled) {
rv = UA_UInt16_decodeBinary(src, offset, &dst->status);
rv = DECODE_BINARY(&dst->status, UINT16);
UA_CHECK_STATUS(rv, return rv);
} else {
dst->status = 0;
}
if(dst->configVersionMajorVersionEnabled) {
rv = UA_UInt32_decodeBinary(src, offset, &dst->configVersionMajorVersion);
rv = DECODE_BINARY(&dst->configVersionMajorVersion, UINT32);
UA_CHECK_STATUS(rv, return rv);
} else {
dst->configVersionMajorVersion = 0;
}
if(dst->configVersionMinorVersionEnabled) {
rv = UA_UInt32_decodeBinary(src, offset, &dst->configVersionMinorVersion);
rv = DECODE_BINARY(&dst->configVersionMinorVersion, UINT32);
UA_CHECK_STATUS(rv, return rv);
} else {
dst->configVersionMinorVersion = 0;
@@ -1394,34 +1392,32 @@ UA_DataSetMessage_keyFrame_encodeBinary(const UA_DataSetMessage* src, UA_Byte **
if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
rv = UA_Variant_encodeBinary(&v->value, bufPos, bufEnd);
} else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
UA_FieldMetaData *fmd =
&src->data.keyFrameData.dataSetMetaDataType->fields[i];
// For arrays we need to encode the dimension sizes before the actual data
UA_FieldMetaData *fmd = &src->data.keyFrameData.dataSetMetaDataType->fields[i];
/* For arrays we need to encode the dimension sizes before the actual data */
size_t elementCount = 1;
for(size_t cnt = 0; cnt < fmd->arrayDimensionsSize; cnt++) {
elementCount *= fmd->arrayDimensions[cnt];
rv = UA_UInt32_encodeBinary(&fmd->arrayDimensions[cnt], bufPos, bufEnd);
UA_CHECK_STATUS(rv, return rv);
}
// Check if Array size matches the one specified in metadata
if(fmd->valueRank > 0 && elementCount != v->value.arrayLength) {
/* Check if Array size matches the one specified in metadata */
if(fmd->valueRank > 0 && elementCount != v->value.arrayLength)
return UA_STATUSCODE_BADENCODINGERROR;
}
UA_Byte *valuePtr = (UA_Byte *)v->value.data;
for(size_t cnt = 0; cnt < elementCount; cnt++) {
if(fmd->maxStringLength != 0 &&
(v->value.type->typeKind == UA_DATATYPEKIND_STRING ||
v->value.type->typeKind == UA_DATATYPEKIND_BYTESTRING)) {
rv = UA_encodeBinaryInternal(valuePtr, v->value.type, bufPos, &bufEnd,
NULL, NULL);
size_t lengthDifference =
fmd->maxStringLength - ((UA_String *)valuePtr)->length;
rv = UA_encodeBinaryInternal(valuePtr, v->value.type, bufPos, &bufEnd, NULL, NULL);
size_t lengthDifference = fmd->maxStringLength - ((UA_String *)valuePtr)->length;
memset(*bufPos, 0, lengthDifference);
*bufPos += lengthDifference;
} else {
/* padding not yet supported for strings as part of structures */
rv = UA_encodeBinaryInternal(valuePtr, v->value.type, bufPos, &bufEnd,
NULL, NULL);
/* Padding not yet supported for strings as part of structures */
rv = UA_encodeBinaryInternal(valuePtr, v->value.type, bufPos, &bufEnd, NULL, NULL);
}
valuePtr += v->value.type->memSize;
}
@@ -1495,22 +1491,20 @@ UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
}
static UA_StatusCode
UA_DataSetMessage_keyFrame_decodeBinary(const UA_ByteString *src, size_t *offset,
size_t initialOffset, UA_DataSetMessage* dst,
size_t dsmSize, const UA_DecodeBinaryOptions *options) {
if(*offset == src->length)
UA_DataSetMessage_keyFrame_decodeBinary(Ctx *ctx, UA_Byte *initialPos, UA_DataSetMessage* dst,
size_t dsmSize) {
if(ctx->pos == ctx->end)
return UA_STATUSCODE_GOOD; /* Messages ends after the header --> Heartbeat */
UA_StatusCode rv = UA_STATUSCODE_GOOD;
UA_DataSetMessage_DataKeyFrameData *kfd = &dst->data.keyFrameData;
switch(dst->header.fieldEncoding) {
case UA_FIELDENCODING_VARIANT:
rv = UA_UInt16_decodeBinary(src, offset, &kfd->fieldCount);
rv = DECODE_BINARY(&kfd->fieldCount, UINT16);
UA_CHECK_STATUS(rv, return rv);
kfd->dataSetFields = (UA_DataValue *)
UA_Array_new(dst->data.keyFrameData.fieldCount,
&UA_TYPES[UA_TYPES_DATAVALUE]);
ctxCalloc(ctx, dst->data.keyFrameData.fieldCount, sizeof(UA_DataValue));
if(!kfd->dataSetFields) {
kfd->fieldCount = 0;
return UA_STATUSCODE_BADOUTOFMEMORY;
@@ -1518,41 +1512,43 @@ UA_DataSetMessage_keyFrame_decodeBinary(const UA_ByteString *src, size_t *offset
for(UA_UInt16 i = 0; i < kfd->fieldCount; i++) {
UA_DataValue_init(&kfd->dataSetFields[i]);
rv = UA_decodeBinaryInternal(src, offset, &kfd->dataSetFields[i].value,
&UA_TYPES[UA_TYPES_VARIANT], options);
rv = DECODE_BINARY(&kfd->dataSetFields[i].value, VARIANT);
UA_CHECK_STATUS(rv, return rv);
kfd->dataSetFields[i].hasValue = true;
}
break;
case UA_FIELDENCODING_DATAVALUE:
rv = UA_UInt16_decodeBinary(src, offset, &kfd->fieldCount);
rv = DECODE_BINARY(&kfd->fieldCount, UINT16);
UA_CHECK_STATUS(rv, return rv);
kfd->dataSetFields = (UA_DataValue *)
UA_Array_new(kfd->fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
ctxCalloc(ctx, kfd->fieldCount, sizeof(UA_DataValue));
if(!kfd->dataSetFields) {
kfd->fieldCount = 0;
return UA_STATUSCODE_BADOUTOFMEMORY;
}
for(UA_UInt16 i = 0; i < kfd->fieldCount; i++) {
rv = UA_decodeBinaryInternal(src, offset, &kfd->dataSetFields[i],
&UA_TYPES[UA_TYPES_DATAVALUE], options);
rv = DECODE_BINARY(&kfd->dataSetFields[i], DATAVALUE);
UA_CHECK_STATUS(rv, return rv);
}
break;
case UA_FIELDENCODING_RAWDATA:
case UA_FIELDENCODING_RAWDATA: {
/* If no size is known from the payload header, then the payload fills
* the entire message. In the future we should subtract security footer
* and signature as well (or do that before). */
const UA_Byte *payloadEnd = initialPos + dsmSize;
if(payloadEnd > ctx->end)
return UA_STATUSCODE_BADDECODINGERROR;
if(dsmSize == 0)
dsmSize = src->length - initialOffset;
kfd->rawFields.data = &src->data[*offset];
kfd->rawFields.length = dsmSize;
*offset += (dsmSize - (*offset - initialOffset));
payloadEnd = ctx->end;
kfd->rawFields.data = ctx->pos;
kfd->rawFields.length = (size_t)(uintptr_t)(payloadEnd - ctx->pos);
ctx->pos = (UA_Byte*)(uintptr_t)payloadEnd;
break;
}
default:
return UA_STATUSCODE_BADINTERNALERROR;
@@ -1562,9 +1558,7 @@ UA_DataSetMessage_keyFrame_decodeBinary(const UA_ByteString *src, size_t *offset
}
static UA_StatusCode
UA_DataSetMessage_deltaFrame_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_DataSetMessage* dst,
const UA_DecodeBinaryOptions *options) {
UA_DataSetMessage_deltaFrame_decodeBinary(Ctx *ctx, UA_DataSetMessage* dst) {
if(dst->header.fieldEncoding == UA_FIELDENCODING_RAWDATA)
return UA_STATUSCODE_BADNOTIMPLEMENTED;
@@ -1573,30 +1567,26 @@ UA_DataSetMessage_deltaFrame_decodeBinary(const UA_ByteString *src, size_t *offs
return UA_STATUSCODE_BADINTERNALERROR;
UA_DataSetMessage_DataDeltaFrameData *dfd = &dst->data.deltaFrameData;
UA_StatusCode rv = UA_UInt16_decodeBinary(src, offset, &dfd->fieldCount);
UA_StatusCode rv = DECODE_BINARY(&dfd->fieldCount, UINT16);
UA_CHECK_STATUS(rv, return rv);
dfd->deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)
UA_calloc(dfd->fieldCount, sizeof(UA_DataSetMessage_DeltaFrameField));
dfd->deltaFrameFields = (UA_DataSetMessage_DeltaFrameField *)
ctxCalloc(ctx, dfd->fieldCount, sizeof(UA_DataSetMessage_DeltaFrameField));
if(!dst->data.deltaFrameData.deltaFrameFields) {
dfd->fieldCount = 0;
return UA_STATUSCODE_BADOUTOFMEMORY;
}
for(UA_UInt16 i = 0; i < dfd->fieldCount; i++) {
rv = UA_UInt16_decodeBinary(src, offset, &dfd->deltaFrameFields[i].fieldIndex);
rv = DECODE_BINARY(&dfd->deltaFrameFields[i].fieldIndex, UINT16);
UA_CHECK_STATUS(rv, return rv);
if(dst->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
rv = UA_decodeBinaryInternal(src, offset,
&dfd->deltaFrameFields[i].fieldValue.value,
&UA_TYPES[UA_TYPES_VARIANT], options);
rv = DECODE_BINARY(&dfd->deltaFrameFields[i].fieldValue.value, VARIANT);
UA_CHECK_STATUS(rv, return rv);
dfd->deltaFrameFields[i].fieldValue.hasValue = true;
} else {
rv = UA_decodeBinaryInternal(src, offset,
&dfd->deltaFrameFields[i].fieldValue,
&UA_TYPES[UA_TYPES_DATAVALUE], options);
rv = DECODE_BINARY(&dfd->deltaFrameFields[i].fieldValue, DATAVALUE);
UA_CHECK_STATUS(rv, return rv);
}
}
@@ -1605,21 +1595,17 @@ UA_DataSetMessage_deltaFrame_decodeBinary(const UA_ByteString *src, size_t *offs
}
UA_StatusCode
UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_DataSetMessage* dst, UA_UInt16 dsmSize,
const UA_DecodeBinaryOptions *options) {
size_t initialOffset = *offset;
memset(dst, 0, sizeof(UA_DataSetMessage));
UA_StatusCode rv = UA_DataSetMessageHeader_decodeBinary(src, offset, &dst->header);
UA_DataSetMessage_decodeBinary(Ctx *ctx, UA_DataSetMessage *dst, UA_UInt16 dsmSize) {
UA_Byte *initialPos = ctx->pos;
UA_StatusCode rv = UA_DataSetMessageHeader_decodeBinary(ctx, &dst->header);
UA_CHECK_STATUS(rv, return rv);
switch(dst->header.dataSetMessageType) {
case UA_DATASETMESSAGE_DATAKEYFRAME:
rv = UA_DataSetMessage_keyFrame_decodeBinary(src, offset, initialOffset, dst,
dsmSize, options);
rv = UA_DataSetMessage_keyFrame_decodeBinary(ctx, initialPos, dst, dsmSize);
break;
case UA_DATASETMESSAGE_DATADELTAFRAME:
rv = UA_DataSetMessage_deltaFrame_decodeBinary(src, offset, dst, options);
rv = UA_DataSetMessage_deltaFrame_decodeBinary(ctx, dst);
break;
case UA_DATASETMESSAGE_KEEPALIVE:
break; /* Keep-Alive Message contains no Payload Data */
+15 -30
View File
@@ -15,6 +15,8 @@
#include <open62541/pubsub.h>
#include <open62541/server_pubsub.h>
#include "../ua_types_encoding_binary.h"
#ifdef UA_ENABLE_PUBSUB
_UA_BEGIN_DECLS
@@ -75,8 +77,7 @@ UA_StatusCode
UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer);
UA_StatusCode
UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
const UA_ByteString *src, size_t *bufferPosition);
UA_NetworkMessage_updateBufferedNwMessage(Ctx *ctx, UA_NetworkMessageOffsetBuffer *buffer);
size_t
UA_NetworkMessage_calcSizeBinaryWithOffsetBuffer(
@@ -87,43 +88,40 @@ UA_NetworkMessage_calcSizeBinaryWithOffsetBuffer(
* ^^^^^^^^^^^^^^ */
UA_StatusCode
UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src,
UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader *src,
UA_Byte **bufPos, const UA_Byte *bufEnd);
UA_StatusCode
UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_DataSetMessageHeader* dst);
UA_DataSetMessageHeader_decodeBinary(Ctx *ctx, UA_DataSetMessageHeader *dst);
UA_StatusCode
UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
UA_DataSetMessage_encodeBinary(const UA_DataSetMessage *src, UA_Byte **bufPos,
const UA_Byte *bufEnd);
UA_StatusCode
UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_DataSetMessage* dst, UA_UInt16 dsmSize,
const UA_DecodeBinaryOptions *options);
UA_DataSetMessage_decodeBinary(Ctx *ctx, UA_DataSetMessage *dst, UA_UInt16 dsmSize);
size_t
UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage *p,
UA_NetworkMessageOffsetBuffer *offsetBuffer,
size_t currentOffset);
void UA_DataSetMessage_clear(UA_DataSetMessage* p);
void UA_DataSetMessage_clear(UA_DataSetMessage *p);
/**
* NetworkMessage Encoding
* ^^^^^^^^^^^^^^^^^^^^^^^ */
UA_StatusCode
UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage* src,
UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage *src,
UA_Byte **bufPos, const UA_Byte *bufEnd);
UA_StatusCode
UA_NetworkMessage_encodePayload(const UA_NetworkMessage* src,
UA_NetworkMessage_encodePayload(const UA_NetworkMessage *src,
UA_Byte **bufPos, const UA_Byte *bufEnd);
UA_StatusCode
UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src,
UA_NetworkMessage_encodeFooters(const UA_NetworkMessage *src,
UA_Byte **bufPos, const UA_Byte *bufEnd);
/**
@@ -131,22 +129,14 @@ UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src,
* ^^^^^^^^^^^^^^^^^^^^^^^ */
UA_StatusCode
UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage *dst);
UA_NetworkMessage_decodeHeaders(Ctx *ctx, UA_NetworkMessage *dst);
UA_StatusCode
UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage *dst,
const UA_DecodeBinaryOptions *options);
UA_NetworkMessage_decodePayload(Ctx *ctx, UA_NetworkMessage *dst);
UA_StatusCode
UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage *dst);
UA_StatusCode
UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage *dst);
UA_NetworkMessage_decodeFooters(Ctx *ctx, UA_NetworkMessage *dst);
UA_StatusCode
UA_NetworkMessage_encodeJsonInternal(const UA_NetworkMessage *src,
UA_Byte **bufPos, const UA_Byte **bufEnd,
@@ -165,11 +155,6 @@ UA_NetworkMessage_encodeBinaryWithEncryptStart(const UA_NetworkMessage* src,
UA_Byte **bufPos, const UA_Byte *bufEnd,
UA_Byte **dataToEncryptStart);
UA_StatusCode
UA_NetworkMessage_decodeBinaryWithOffset(const UA_ByteString *src, size_t *offset,
UA_NetworkMessage* dst,
const UA_DecodeBinaryOptions *options);
#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
UA_StatusCode
+20 -16
View File
@@ -967,25 +967,22 @@ UA_DataSetReader_handleMessageReceiveTimeout(UA_Server *server, UA_DataSetReader
#endif /* UA_ENABLE_PUBSUB_MONITORING */
UA_StatusCode
UA_DataSetReader_prepareOffsetBuffer(UA_Server *server, UA_DataSetReader *reader,
UA_ByteString *buf, size_t *pos) {
UA_NetworkMessage *nm = (UA_NetworkMessage*)UA_calloc(1, sizeof(UA_NetworkMessage));
UA_DataSetReader_prepareOffsetBuffer(Ctx *ctx, UA_DataSetReader *reader,
UA_ByteString *buf) {
UA_NetworkMessage *nm = (UA_NetworkMessage *)
UA_calloc(1, sizeof(UA_NetworkMessage));
if(!nm)
return UA_STATUSCODE_BADOUTOFMEMORY;
UA_DecodeBinaryOptions opt;
memset(&opt, 0, sizeof(UA_DecodeBinaryOptions));
opt.customTypes = server->config.customDataTypes;
/* Decode using the non-rt decoding */
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(buf, pos, nm);
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(ctx, nm);
if(rv != UA_STATUSCODE_GOOD) {
UA_NetworkMessage_clear(nm);
UA_free(nm);
return rv;
}
rv |= UA_NetworkMessage_decodePayload(buf, pos, nm, &opt);
rv |= UA_NetworkMessage_decodeFooters(buf, pos, nm);
rv |= UA_NetworkMessage_decodePayload(ctx, nm);
rv |= UA_NetworkMessage_decodeFooters(ctx, nm);
if(rv != UA_STATUSCODE_GOOD) {
UA_NetworkMessage_clear(nm);
UA_free(nm);
@@ -1009,20 +1006,27 @@ UA_DataSetReader_prepareOffsetBuffer(UA_Server *server, UA_DataSetReader *reader
void
UA_DataSetReader_decodeAndProcessRT(UA_Server *server, UA_DataSetReader *dsr,
UA_ByteString *buf) {
size_t pos = 0;
/* Set up the decoding context */
Ctx ctx;
ctx.pos = buf->data;
ctx.end = buf->data + buf->length;
ctx.depth = 0;
memset(&ctx.opts, 0, sizeof(UA_DecodeBinaryOptions));
ctx.opts.customTypes = server->config.customDataTypes;
UA_StatusCode rv;
if(!dsr->bufferedMessage.nm) {
/* This is the first message being received for the RT fastpath.
* Prepare the offset buffer. */
rv = UA_DataSetReader_prepareOffsetBuffer(server, dsr, buf, &pos);
rv = UA_DataSetReader_prepareOffsetBuffer(&ctx, dsr, buf);
} else {
/* Decode with offset information and update the networkMessage */
rv = UA_NetworkMessage_updateBufferedNwMessage(&dsr->bufferedMessage, buf, &pos);
rv = UA_NetworkMessage_updateBufferedNwMessage(&ctx, &dsr->bufferedMessage);
}
if(rv != UA_STATUSCODE_GOOD) {
UA_LOG_INFO_READER(server->config.logging, dsr,
"PubSub decoding failed. Could not decode with "
"status code %s.", UA_StatusCode_name(rv));
UA_LOG_WARNING_READER(server->config.logging, dsr,
"PubSub decoding failed. Could not decode with "
"status code %s.", UA_StatusCode_name(rv));
return;
}
+10 -4
View File
@@ -716,6 +716,14 @@ UA_ReaderGroup_decodeAndProcessRT(UA_Server *server, UA_ReaderGroup *rg,
if(rg->state == UA_PUBSUBSTATE_PREOPERATIONAL)
UA_ReaderGroup_setPubSubState(server, rg, UA_PUBSUBSTATE_OPERATIONAL);
/* Set up the decoding context */
Ctx ctx;
ctx.pos = buf->data;
ctx.end = buf->data + buf->length;
ctx.depth = 0;
memset(&ctx.opts, 0, sizeof(UA_DecodeBinaryOptions));
ctx.opts.customTypes = server->config.customDataTypes;
UA_Boolean processed = false;
UA_NetworkMessage currentNetworkMessage;
memset(&currentNetworkMessage, 0, sizeof(UA_NetworkMessage));
@@ -729,8 +737,7 @@ UA_ReaderGroup_decodeAndProcessRT(UA_Server *server, UA_ReaderGroup *rg,
#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
useMembufAlloc();
#endif
size_t pos = 0;
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(buf, &pos, &currentNetworkMessage);
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(&ctx, &currentNetworkMessage);
#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
useNormalAlloc();
#endif
@@ -742,8 +749,7 @@ UA_ReaderGroup_decodeAndProcessRT(UA_Server *server, UA_ReaderGroup *rg,
/* Decrypt the message. Keep pos right after the header. */
#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
rv = verifyAndDecryptNetworkMessage(server->config.logging, buf, &pos,
&currentNetworkMessage, rg);
rv = verifyAndDecryptNetworkMessage(server->config.logging, &ctx, &currentNetworkMessage, rg);
if(rv != UA_STATUSCODE_GOOD) {
UA_LOG_WARNING_READERGROUP(server->config.logging, rg,
"Subscribe failed. verify and decrypt network "
+18 -26
View File
@@ -8,17 +8,14 @@
#include "ua_pubsub.h"
#include "util/ua_util_internal.h"
static
UA_StatusCode
static UA_StatusCode
needsDecryption(const UA_Logger *logger,
const UA_NetworkMessage *networkMessage,
const UA_MessageSecurityMode securityMode,
UA_Boolean *doDecrypt) {
UA_Boolean isEncrypted = networkMessage->securityHeader.networkMessageEncrypted;
UA_Boolean requiresEncryption = securityMode > UA_MESSAGESECURITYMODE_SIGN;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_Boolean requiresEncryption = securityMode > UA_MESSAGESECURITYMODE_SIGN;
UA_Boolean isEncrypted = networkMessage->securityHeader.networkMessageEncrypted;
if(isEncrypted && requiresEncryption) {
*doDecrypt = true;
@@ -45,9 +42,9 @@ needsValidation(const UA_Logger *logger,
const UA_NetworkMessage *networkMessage,
const UA_MessageSecurityMode securityMode,
UA_Boolean *doValidate) {
UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_Boolean isSigned = networkMessage->securityHeader.networkMessageSigned;
UA_Boolean requiresSignature = securityMode > UA_MESSAGESECURITYMODE_NONE;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(isSigned &&
requiresSignature) {
@@ -55,7 +52,6 @@ needsValidation(const UA_Logger *logger,
} else if(!isSigned && !requiresSignature) {
*doValidate = false;
} else {
if(isSigned) {
UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURITYPOLICY,
"PubSub receive. "
@@ -72,26 +68,24 @@ needsValidation(const UA_Logger *logger,
}
UA_StatusCode
verifyAndDecrypt(const UA_Logger *logger, UA_ByteString *buffer,
const size_t *currentPosition, const UA_NetworkMessage *nm,
verifyAndDecrypt(const UA_Logger *logger, Ctx *ctx, const UA_NetworkMessage *nm,
UA_Boolean doValidate, UA_Boolean doDecrypt, void *channelContext,
UA_PubSubSecurityPolicy *securityPolicy) {
UA_StatusCode rv = UA_STATUSCODE_GOOD;
if(doValidate) {
size_t sigSize = securityPolicy->symmetricModule.cryptoModule.
signatureAlgorithm.getLocalSignatureSize(channelContext);
UA_ByteString toBeVerified = {buffer->length - sigSize, buffer->data};
UA_ByteString signature = {sigSize, buffer->data + buffer->length - sigSize};
UA_ByteString toBeVerified = {(uintptr_t)(ctx->end - ctx->pos) - sigSize, ctx->pos};
UA_ByteString signature = {sigSize, (UA_Byte*)(uintptr_t)(ctx->end - sigSize)};
rv = securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
UA_StatusCode rv =
securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
verify(channelContext, &toBeVerified, &signature);
UA_CHECK_STATUS_WARN(rv, return rv, logger, UA_LOGCATEGORY_SECURITYPOLICY,
"PubSub receive. Signature invalid");
UA_LOG_DEBUG(logger, UA_LOGCATEGORY_SECURITYPOLICY,
"PubSub receive. Signature valid");
buffer->length -= sigSize;
ctx->end -= sigSize;
}
if(doDecrypt) {
@@ -99,14 +93,13 @@ verifyAndDecrypt(const UA_Logger *logger, UA_ByteString *buffer,
(size_t)nm->securityHeader.messageNonceSize,
(UA_Byte*)(uintptr_t)nm->securityHeader.messageNonce
};
rv = securityPolicy->setMessageNonce(channelContext, &nonce);
UA_StatusCode rv = securityPolicy->setMessageNonce(channelContext, &nonce);
UA_CHECK_STATUS_WARN(rv, return rv, logger, UA_LOGCATEGORY_SECURITYPOLICY,
"PubSub receive. Faulty Nonce set");
UA_ByteString toBeDecrypted = {buffer->length - *currentPosition,
buffer->data + *currentPosition};
UA_ByteString toBeDecrypted = {(uintptr_t)(ctx->end - ctx->pos), ctx->pos};
rv = securityPolicy->symmetricModule.cryptoModule
.encryptionAlgorithm.decrypt(channelContext, &toBeDecrypted);
.encryptionAlgorithm.decrypt(channelContext, &toBeDecrypted);
UA_CHECK_STATUS_WARN(rv, return rv, logger, UA_LOGCATEGORY_SECURITYPOLICY,
"PubSub receive. Faulty Decryption");
}
@@ -114,15 +107,14 @@ verifyAndDecrypt(const UA_Logger *logger, UA_ByteString *buffer,
}
UA_StatusCode
verifyAndDecryptNetworkMessage(const UA_Logger *logger, UA_ByteString *buffer,
size_t *currentPosition, UA_NetworkMessage *nm,
verifyAndDecryptNetworkMessage(const UA_Logger *logger, Ctx *ctx,
UA_NetworkMessage *nm,
UA_ReaderGroup *readerGroup) {
UA_MessageSecurityMode securityMode = readerGroup->config.securityMode;
UA_Boolean doValidate = false;
UA_Boolean doDecrypt = false;
UA_StatusCode rv = UA_STATUSCODE_GOOD;
rv = needsValidation(logger, nm, securityMode, &doValidate);
UA_StatusCode rv = needsValidation(logger, nm, securityMode, &doValidate);
UA_CHECK_STATUS_WARN(rv, return rv, logger, UA_LOGCATEGORY_SECURITYPOLICY,
"PubSub receive. Validation security mode error");
@@ -142,8 +134,8 @@ verifyAndDecryptNetworkMessage(const UA_Logger *logger, UA_ByteString *buffer,
"PubSub receive. securityPolicy must be set when security mode"
"is enabled to sign and/or encrypt");
rv = verifyAndDecrypt(logger, buffer, currentPosition, nm,
doValidate, doDecrypt, channelContext, securityPolicy);
rv = verifyAndDecrypt(logger, ctx, nm, doValidate, doDecrypt,
channelContext, securityPolicy);
UA_CHECK_STATUS_ERROR(rv, return rv, logger, UA_LOGCATEGORY_SERVER,
"PubSub receive. verify and decrypt failed");
-18
View File
@@ -68,12 +68,6 @@ ctxClearNodeId(Ctx *ctx, UA_NodeId *p) {
memset(p, 0, sizeof(UA_NodeId));
}
typedef status
(*encodeBinarySignature)(Ctx *UA_RESTRICT ctx, const void *UA_RESTRICT src,
const UA_DataType *type);
typedef status
(*decodeBinarySignature)(Ctx *UA_RESTRICT ctx, void *UA_RESTRICT dst,
const UA_DataType *type);
#define ENCODE_BINARY(TYPE) static status \
TYPE##_encodeBinary(Ctx *UA_RESTRICT ctx, \
const UA_##TYPE *UA_RESTRICT src, \
@@ -91,13 +85,6 @@ typedef status
return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; \
} else \
/* Jumptables for de-/encoding and computing the buffer length. The methods in
* the decoding jumptable do not all clean up their allocated memory when an
* error occurs. So a final _clear needs to be called before returning to the
* user. */
extern const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS];
extern const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS];
/* Send the current chunk and replace the buffer */
static status exchangeBuffer(Ctx *ctx) {
if(!ctx->exchangeBufferCallback)
@@ -1848,11 +1835,6 @@ const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS] = {
(decodeBinarySignature)decodeBinaryNotImplemented /* BitfieldCluster */
};
status
UA_decodeBinaryInternalCtx(Ctx *ctx, void *dst, const UA_DataType *type) {
return decodeBinaryJumpTable[type->typeKind](ctx, dst, type);
}
status
UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
void *dst, const UA_DataType *type,
+13 -7
View File
@@ -37,6 +37,19 @@ void * ctxCalloc(Ctx *ctx, size_t nelem, size_t elsize);
void ctxFree(Ctx *ctx, void *p);
void ctxClear(Ctx *ctx, void *p, const UA_DataType *type);
/* Jumptables for de-/encoding and computing the buffer length. The methods in
* the decoding jumptable do not memset-zero initially and do not clean up their
* allocated memory when an error occurs. So a final _clear needs to be called
* before returning to the user. */
typedef UA_StatusCode
(*encodeBinarySignature)(Ctx *UA_RESTRICT ctx, const void *UA_RESTRICT src,
const UA_DataType *type);
typedef UA_StatusCode
(*decodeBinarySignature)(Ctx *UA_RESTRICT ctx, void *UA_RESTRICT dst,
const UA_DataType *type);
extern const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS];
extern const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS];
/* Encodes the scalar value described by type in the binary encoding. Encoding
* is thread-safe if thread-local variables are enabled. Encoding is also
* reentrant and can be safely called from signal handlers or interrupts.
@@ -84,13 +97,6 @@ UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
const UA_DecodeBinaryOptions *options)
UA_FUNC_ATTR_WARN_UNUSED_RESULT;
/* Call into decoding with an existing context.
* Beware! This assumes the dst is already memset-zero and will not clear up if
* decoding fails. */
UA_StatusCode
UA_decodeBinaryInternalCtx(Ctx *ctx, void *dst, const UA_DataType *type)
UA_FUNC_ATTR_WARN_UNUSED_RESULT;
const UA_DataType *
UA_findDataTypeByBinary(const UA_NodeId *typeId);