mirror of
https://github.com/open62541/open62541.git
synced 2026-10-16 20:33:18 +08:00
refactor(pubsub): Use decoding Ctx structure directly
This commit is contained in:
committed by
Julius Pfrommer
parent
5e23a43ab9
commit
6d923ff37d
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(¤tNetworkMessage, 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, ¤tNetworkMessage);
|
||||
UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(&ctx, ¤tNetworkMessage);
|
||||
#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,
|
||||
¤tNetworkMessage, rg);
|
||||
rv = verifyAndDecryptNetworkMessage(server->config.logging, &ctx, ¤tNetworkMessage, rg);
|
||||
if(rv != UA_STATUSCODE_GOOD) {
|
||||
UA_LOG_WARNING_READERGROUP(server->config.logging, rg,
|
||||
"Subscribe failed. verify and decrypt network "
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user