From d18ae43123fcd7604d1c36a1ec8450dbe6071824 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Thu, 23 Feb 2017 20:44:26 +0100 Subject: Initial commit: ccnxlibs. Change-Id: I1b376527a7dd01a6b9e083a6cb646955902f45c0 Signed-off-by: Luca Muscariello --- .../schema_v1/ccnxCodecSchemaV1_MessageEncoder.c | 340 +++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100755 libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c (limited to 'libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c') diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c new file mode 100755 index 00000000..7aa14627 --- /dev/null +++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + */ + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +static ssize_t +_encodeName(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = -1; + CCNxName *name = ccnxTlvDictionary_GetName(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME); + if (name != NULL) { + length = ccnxCodecSchemaV1NameCodec_Encode(encoder, CCNxCodecSchemaV1Types_CCNxMessage_Name, name); + } + + // required field for everything except CCNxContentObjects + if (!ccnxTlvDictionary_IsContentObject(packetDictionary) && length < 0) { + CCNxCodecError *error = ccnxCodecError_Create(TLV_MISSING_MANDATORY, __func__, __LINE__, ccnxCodecTlvEncoder_Position(encoder)); + ccnxCodecTlvEncoder_SetError(encoder, error); + ccnxCodecError_Release(&error); + } else if (ccnxTlvDictionary_IsContentObject(packetDictionary) && name == NULL) { + length = 0; + } + + return length; +} + +static ssize_t +_encodeJsonPayload(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + PARCJSON *json = ccnxTlvDictionary_GetJson(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD); + if (json != NULL) { + char *jsonString = parcJSON_ToCompactString(json); + size_t len = strlen(jsonString); + length = ccnxCodecTlvEncoder_AppendArray(encoder, CCNxCodecSchemaV1Types_CCNxMessage_Payload, len, (uint8_t *) jsonString); + } + return length; +} + +static ssize_t +_encodePayload(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD); + if (buffer != NULL) { + length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_Payload, buffer); + } + return length; +} + +static ssize_t +_encodePayloadType(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE)) { + CCNxPayloadType payloadType = (CCNxPayloadType) ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE); + + CCNxCodecSchemaV1Types_PayloadType wireFormatType = CCNxCodecSchemaV1Types_PayloadType_Data; + + switch (payloadType) { + case CCNxPayloadType_KEY: + wireFormatType = CCNxCodecSchemaV1Types_PayloadType_Key; + break; + + case CCNxPayloadType_LINK: + wireFormatType = CCNxCodecSchemaV1Types_PayloadType_Link; + break; + + default: + // anything else is encoded as DATA + break; + } + + length = ccnxCodecTlvEncoder_AppendUint8(encoder, CCNxCodecSchemaV1Types_CCNxMessage_PayloadType, wireFormatType); + } else if (ccnxTlvDictionary_IsValueBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE)) { + PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE); + length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_PayloadType, buffer); + } + + return length; +} + +static ssize_t +_encodeExpiryTime(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME)) { + uint64_t millis = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME); + length = ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxMessage_ExpiryTime, millis); + } else if (ccnxTlvDictionary_IsValueBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME)) { + PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME); + length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_ExpiryTime, buffer); + } + + return length; +} + +static ssize_t +_encodeEndChunkNumber(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT)) { + uint64_t endChunkId = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT); + length = ccnxCodecTlvEncoder_AppendVarInt(encoder, CCNxCodecSchemaV1Types_CCNxMessage_EndChunkNumber, endChunkId); + } else { + PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT); + if (buffer != NULL) { + length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_EndChunkNumber, buffer); + } + } + return length; +} + +static ssize_t +_encodeKeyIdRestriction(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + PARCCryptoHash *hash = ccnxTlvDictionary_GetObject(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION); + if (hash != NULL) { + size_t startPosition = ccnxCodecTlvEncoder_Position(encoder); + ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_KeyIdRestriction, 0); + length = ccnxCodecSchemaV1HashCodec_Encode(encoder, hash); + if (length < 0) { + return length; + } + + ccnxCodecTlvEncoder_SetContainerLength(encoder, startPosition, length); + length += 4; // this accounts for the TL fields + } + return length; +} + +static ssize_t +_encodeContentObjectHashRestriction(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + PARCCryptoHash *hash = ccnxTlvDictionary_GetObject(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION); + if (hash != NULL) { + size_t startPosition = ccnxCodecTlvEncoder_Position(encoder); + ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_ContentObjectHashRestriction, 0); + length = ccnxCodecSchemaV1HashCodec_Encode(encoder, hash); + if (length < 0) { + return length; + } + + ccnxCodecTlvEncoder_SetContainerLength(encoder, startPosition, length); + length += 4; // this accounts for the TL fields + } + return length; +} + + +static ssize_t +_encodeContentObject(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + ssize_t result; + + result = _encodeName(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = _encodePayloadType(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = _encodeExpiryTime(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = _encodeEndChunkNumber(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = _encodePayload(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + return length; +} + +static ssize_t +_encodeInterest(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + ssize_t result; + + result = _encodeName(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = _encodeKeyIdRestriction(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = _encodeContentObjectHashRestriction(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = _encodePayload(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + return length; +} + +static ssize_t +_encodeControl(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + ssize_t result; + + result = _encodeName(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = _encodeJsonPayload(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + return length; +} + +static ssize_t +_encodeManifest(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + ssize_t length = 0; + ssize_t result; + + result = _encodeName(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + result = ccnxCodecSchemaV1ManifestEncoder_Encode(encoder, packetDictionary); + if (result < 0) { + return result; + } + length += result; + + return length; +} + +ssize_t +ccnxCodecSchemaV1MessageEncoder_Encode(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary) +{ + assertNotNull(encoder, "Parameter encoder must be non-null"); + assertNotNull(packetDictionary, "Parameter packetDictionary must be non-null"); + + ssize_t length = -1; + + if (ccnxTlvDictionary_IsInterest(packetDictionary)) { + length = _encodeInterest(encoder, packetDictionary); + } else if (ccnxTlvDictionary_IsInterestReturn(packetDictionary)) { + length = _encodeInterest(encoder, packetDictionary); + } else if (ccnxTlvDictionary_IsContentObject(packetDictionary)) { + length = _encodeContentObject(encoder, packetDictionary); + } else if (ccnxTlvDictionary_IsControl(packetDictionary)) { + length = _encodeControl(encoder, packetDictionary); + } else if (ccnxTlvDictionary_IsManifest(packetDictionary)) { + length = _encodeManifest(encoder, packetDictionary); + } else { + CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETTYPE, __func__, __LINE__, ccnxCodecTlvEncoder_Position(encoder)); + ccnxCodecTlvEncoder_SetError(encoder, error); + ccnxCodecError_Release(&error); + length = -1; + } + + + if (length >= 0) { + // Put custom fields all last + ssize_t customLength = ccnxCodecTlvUtilities_EncodeCustomList(encoder, packetDictionary, CCNxCodecSchemaV1TlvDictionary_Lists_MESSAGE_LIST); + if (customLength < 0) { + return customLength; + } + length += customLength; + } + + return length; +} -- cgit 1.2.3-korg