summaryrefslogtreecommitdiffstats
path: root/libccnx-common/ccnx/common/internal
diff options
context:
space:
mode:
Diffstat (limited to 'libccnx-common/ccnx/common/internal')
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_ChunkingFacadeV1.c60
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_ChunkingFacadeV1.h103
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_ContentObjectFacadeV1.c294
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_ContentObjectFacadeV1.h34
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_ContentObjectInterface.c54
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_ContentObjectInterface.h145
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_InterestDefault.c24
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_InterestDefault.h50
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_InterestFacadeV1.c295
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_InterestFacadeV1.h29
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_InterestInterface.c53
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_InterestInterface.h130
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_InterestPayloadIdMethod.h28
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_InterestReturnFacadeV1.c100
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_InterestReturnFacadeV1.h29
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_InterestReturnInterface.c55
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_InterestReturnInterface.h71
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_ManifestFacadeV1.c132
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_ManifestFacadeV1.h30
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_ManifestInterface.c55
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_ManifestInterface.h64
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_MessageInterface.h33
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_TlvDictionary.c1022
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h1127
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_TlvError.c167
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_ValidationFacadeV1.c203
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_ValidationFacadeV1.h474
-rw-r--r--libccnx-common/ccnx/common/internal/ccnx_WireFormatFacadeV1.c484
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_WireFormatFacadeV1.h42
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_WireFormatMessageInterface.c46
-rwxr-xr-xlibccnx-common/ccnx/common/internal/ccnx_WireFormatMessageInterface.h121
-rw-r--r--libccnx-common/ccnx/common/internal/test/.gitignore18
-rw-r--r--libccnx-common/ccnx/common/internal/test/CMakeLists.txt24
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_ChunkingFacadebin0 -> 185076 bytes
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_ChunkingFacadeV1.c261
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectFacadebin0 -> 206292 bytes
-rw-r--r--libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectFacadeV1.c377
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectInterface.c106
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_InterestFacadeV1.c334
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_InterestInterface.c107
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_InterestReturnFacadeV1.c168
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_InterestReturnInterface.c112
-rw-r--r--libccnx-common/ccnx/common/internal/test/test_ccnx_ManifestFacadeV1.c.c223
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_ManifestInterface.c.c100
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_TlvDictionary.c1142
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_ValidationFacadebin0 -> 207544 bytes
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_ValidationFacadeV1.c444
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c594
48 files changed, 9564 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ChunkingFacadeV1.c b/libccnx-common/ccnx/common/internal/ccnx_ChunkingFacadeV1.c
new file mode 100755
index 00000000..5af1b5ca
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ChunkingFacadeV1.c
@@ -0,0 +1,60 @@
+/*
+ * 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/internal/ccnx_ChunkingFacadeV1.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+static void
+_assertInvariants(const CCNxTlvDictionary *dictionary)
+{
+ assertNotNull(dictionary, "Parameter contentObjectDictionary must be non-null");
+ trapIllegalValueIf(ccnxTlvDictionary_GetSchemaVersion(dictionary) != CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema version, expected %d got %d",
+ CCNxTlvDictionary_SchemaVersion_V1,
+ ccnxTlvDictionary_GetSchemaVersion(dictionary));
+}
+
+bool
+ccnxChunkingFacadeV1_HasEndChunkNumber(const CCNxTlvDictionary *contentObjectDictionary)
+{
+ _assertInvariants(contentObjectDictionary);
+ return ccnxTlvDictionary_IsValueInteger(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT);
+}
+
+uint64_t
+ccnxChunkingFacadeV1_GetEndChunkNumber(const CCNxTlvDictionary *contentObjectDictionary)
+{
+ _assertInvariants(contentObjectDictionary);
+ return ccnxTlvDictionary_GetInteger(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT);
+}
+
+bool
+ccnxChunkingFacadeV1_SetEndChunkNumber(CCNxTlvDictionary *contentObjectDictionary, uint64_t endChunkNumber)
+{
+ _assertInvariants(contentObjectDictionary);
+ trapIllegalValueIf(!ccnxTlvDictionary_IsContentObject(contentObjectDictionary), "Dictionary is not a ContentObject");
+ return ccnxTlvDictionary_PutInteger(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT, endChunkNumber);
+}
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ChunkingFacadeV1.h b/libccnx-common/ccnx/common/internal/ccnx_ChunkingFacadeV1.h
new file mode 100755
index 00000000..a4d2010c
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ChunkingFacadeV1.h
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ccnx_ChunkingFacade.h
+ * @brief <#Brief Description#>
+ *
+ * <#Detailed Description#>
+ *
+ */
+
+#ifndef libccnx_ccnx_ChunkingFacadeV1_h
+#define libccnx_ccnx_ChunkingFacadeV1_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+
+/**
+ * Determines if an EndChunkNumber exists in the metadata
+ *
+ * Compatible with V0 and V1 schemas.
+ *
+ * @param [in] contentObjectDictionary A dictionary to check
+ *
+ * @return false There is no EndChunkNumber specified or the dictinoary is not a ContentObject
+ * @return true There is an EndChunkNumber specified
+ *
+ * Example:
+ * @code
+ * static PARCElasticBuffer *
+ * _ccnxContentObjectFacade_CreateFinalBlockId(const CCNxTlvDictionary *contentObjectDictionary)
+ * {
+ * if (ccnxChunkingFacade_HasEndChunkNumber(contentObjectDictionary)) {
+ * uint64_t endChunkNumber = ccnxChunkingFacade_GetEndChunkNumber(contentObjectDictionary);
+ * PARCElasticBuffer *fbid = _ccnxContentObjectFacade_EncodeFinalBlockId(endChunkNumber);
+ * return fbid;
+ * }
+ * return NULL;
+ * }
+ * @endcode
+ */
+bool ccnxChunkingFacadeV1_HasEndChunkNumber(const CCNxTlvDictionary *contentObjectDictionary);
+
+/**
+ * Retrieves the end chunk number
+ *
+ * Retieves the end chunk number as an unsigned 64-bit integer.
+ * This function will trapIllegalValue if there is not an EndChunkNumber present.
+ * The EndChunkNumber is the chunk number of the last Content Object in a chunked series.
+ *
+ * @param [in] contentObjectDictionary A dictionary to check
+ *
+ * @return number The ending chunk number
+ *
+ * Example:
+ * @code
+ * static PARCElasticBuffer *
+ * _ccnxContentObjectFacade_CreateFinalBlockId(const CCNxTlvDictionary *contentObjectDictionary)
+ * {
+ * if (ccnxChunkingFacade_HasEndChunkNumber(contentObjectDictionary)) {
+ * uint64_t endChunkNumber = ccnxChunkingFacade_GetEndChunkNumber(contentObjectDictionary);
+ * PARCElasticBuffer *fbid = _ccnxContentObjectFacade_EncodeFinalBlockId(endChunkNumber);
+ * return fbid;
+ * }
+ * return NULL;
+ * }
+ * @endcode
+ */
+uint64_t ccnxChunkingFacadeV1_GetEndChunkNumber(const CCNxTlvDictionary *contentObjectDictionary);
+
+/**
+ * Sets the EndChunkNumber of a ContentObject
+ *
+ * The dictionary must be a ContentObject, otherwise this function will trapIllegalValue.
+ * If an EndChunkNumber already exits, will not update but return false.
+ *
+ * @param [in] contentObjectDictionary A dictionary to check
+ * @param [in] endChunkNumber The ending chunk number
+ *
+ * @return true The value was set in the dictionary
+ * @return false A failure (likely value already set)
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxTlvDictionary *obj = ccnxContentObjectFacade_Create(...);
+ * ccnxChunkingFacade_SetEndChunkNumber(obj, 74);
+ * }
+ * @endcode
+ */
+bool ccnxChunkingFacadeV1_SetEndChunkNumber(CCNxTlvDictionary *contentObjectDictionary, uint64_t endChunkNumber);
+#endif // libccnx_ccnx_ChunkingFacadeV1_h
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ContentObjectFacadeV1.c b/libccnx-common/ccnx/common/internal/ccnx_ContentObjectFacadeV1.c
new file mode 100644
index 00000000..1ca0c5af
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ContentObjectFacadeV1.c
@@ -0,0 +1,294 @@
+/*
+ * 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <LongBow/runtime.h>
+
+#include <parc/security/parc_SigningAlgorithm.h>
+
+#include <ccnx/common/internal/ccnx_ContentObjectFacadeV1.h>
+#include <ccnx/common/internal/ccnx_ValidationFacadeV1.h>
+#include <ccnx/common/internal/ccnx_ChunkingFacadeV1.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+
+static void
+_assertInvariants(const CCNxTlvDictionary *contentObjectDictionary)
+{
+ assertNotNull(contentObjectDictionary, "Dictionary is null");
+ assertTrue(ccnxTlvDictionary_IsContentObject(contentObjectDictionary), "Dictionary is not a content object");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(contentObjectDictionary) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Dictionary is wrong schema version, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(contentObjectDictionary), CCNxTlvDictionary_SchemaVersion_V1);
+}
+
+// =========================
+// Creation
+
+static CCNxTlvDictionary *
+_ccnxContentObjectFacadeV1_CreateWithNameAndPayload(const CCNxName *name, // required
+ const CCNxPayloadType payloadType, // required
+ const PARCBuffer *payload) // may be null
+{
+ assertNotNull(name, "Parameter name must be non-null");
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+
+ if (dictionary) {
+ ccnxTlvDictionary_PutName(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME, name);
+
+ if (payloadType != CCNxPayloadType_DATA) {
+ ccnxTlvDictionary_PutInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE, payloadType);
+ }
+
+ if (payload) {
+ ccnxTlvDictionary_PutBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, payload);
+ }
+ } else {
+ trapOutOfMemory("Could not allocate ContentObject");
+ }
+
+ return dictionary;
+}
+
+static CCNxTlvDictionary *
+_ccnxContentObjectFacadeV1_CreateWithPayload(const CCNxPayloadType payloadType, // required
+ const PARCBuffer *payload) // may be null
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+
+ if (dictionary) {
+ if (payloadType != CCNxPayloadType_DATA) {
+ ccnxTlvDictionary_PutInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE, payloadType);
+ }
+
+ if (payload) {
+ ccnxTlvDictionary_PutBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, payload);
+ }
+ } else {
+ trapOutOfMemory("Could not allocate ContentObject");
+ }
+
+ return dictionary;
+}
+
+// =========================
+// Getters
+
+static CCNxName *
+_ccnxContentObjectFacadeV1_GetName(const CCNxTlvDictionary *contentObjectDictionary)
+{
+ _assertInvariants(contentObjectDictionary);
+ return ccnxTlvDictionary_GetName(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME);
+}
+
+static bool
+_ccnxContentObjectFacadeV1_HasExpiryTime(const CCNxTlvDictionary *packetDictionary)
+{
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME)) {
+ return true;
+ }
+ return false;
+}
+
+static uint64_t
+_ccnxContentObjectFacadeV1_GetExpiryTime(const CCNxTlvDictionary *packetDictionary)
+{
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME)) {
+ return ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME);
+ }
+ trapUnexpectedState("The dictionary does not contain an Expiry Time");
+}
+
+static bool
+_ccnxContentObjectFacadeV1_HasPathLabel(const CCNxTlvDictionary *packetDictionary)
+{
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel)) {
+ return true;
+ }
+ return false;
+}
+
+
+static uint64_t
+_ccnxContentObjectFacadeV1_GetPathLabel(const CCNxTlvDictionary *packetDictionary)
+{
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel)) {
+ return ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel);
+ }
+ trapUnexpectedState("The dictionary does not contain a Path Label");
+}
+
+static PARCBuffer *
+_ccnxContentObjectFacadeV1_GetPayload(const CCNxTlvDictionary *contentObjectDictionary)
+{
+ _assertInvariants(contentObjectDictionary);
+ return ccnxTlvDictionary_GetBuffer(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD);
+}
+
+static CCNxPayloadType
+_ccnxContentObjectFacadeV1_GetPayloadType(const CCNxTlvDictionary *contentObjectDictionary)
+{
+ CCNxPayloadType result = CCNxPayloadType_DATA;
+
+ _assertInvariants(contentObjectDictionary);
+ if (ccnxTlvDictionary_IsValueInteger(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE)) {
+ result = (CCNxPayloadType) ccnxTlvDictionary_GetInteger(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE);
+ }
+
+ return result;
+}
+
+// =========================
+// Setters
+
+static bool
+_ccnxContentObjectFacadeV1_SetSignature(CCNxTlvDictionary *contentObject, const PARCBuffer *keyId,
+ const PARCSignature *signature, const CCNxKeyLocator *keyLocator)
+{
+ bool result = false;
+
+ CCNxTlvDictionary *contentObjectDictionary = (CCNxTlvDictionary *) contentObject;
+
+ if (parcSignature_GetSigningAlgorithm(signature) == PARCSigningAlgorithm_RSA
+ && parcSignature_GetHashType(signature) == PARCCryptoHashType_SHA256) {
+ ccnxValidationRsaSha256_Set(contentObjectDictionary, keyId, keyLocator);
+ } else if (parcSignature_GetSigningAlgorithm(signature) == PARCSigningAlgorithm_HMAC
+ && parcSignature_GetHashType(signature) == PARCCryptoHashType_SHA256) {
+ ccnxValidationHmacSha256_Set(contentObjectDictionary, keyId);
+ } else {
+ trapNotImplemented("Have not implemented the signature parameters");
+ }
+
+ PARCBuffer *sigbits = parcSignature_GetSignature(signature);
+
+ result = ccnxValidationFacadeV1_SetPayload(contentObjectDictionary, sigbits);
+
+ return result;
+}
+
+static PARCBuffer *
+_ccnxContentObjectFacadeV1_GetKeyId(const CCNxTlvDictionary *contentObject)
+{
+ return ccnxValidationFacadeV1_GetKeyId(contentObject);
+}
+
+static bool
+_ccnxContentObjectFacadeV1_SetExpiryTime(CCNxTlvDictionary *contentObjectDictionary, uint64_t expiryTime)
+{
+ bool success = ccnxTlvDictionary_PutInteger(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME, expiryTime);
+ trapUnexpectedStateIf(!success, "Could not set integer in dictionary");
+ return success;
+}
+
+static bool
+_ccnxContentObjectFacadeV1_SetPathLabel(CCNxTlvDictionary *contentObjectDictionary, uint64_t pathLabel)
+{
+ bool success = ccnxTlvDictionary_PutInteger(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel, pathLabel);
+ trapUnexpectedStateIf(!success, "Could not set integer in dictionary (path label)");
+ return success;
+}
+
+static bool
+_ccnxContentObjectFacadeV1_SetPayload(CCNxTlvDictionary *contentObjectDictionary, CCNxPayloadType payloadType, const PARCBuffer *payload)
+{
+ bool result = false;
+
+ if (payload != NULL) {
+ PARCBuffer *originalPayload = _ccnxContentObjectFacadeV1_GetPayload(contentObjectDictionary);
+
+ result = ccnxTlvDictionary_PutBuffer(contentObjectDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, payload);
+
+ if (result) {
+ if (_ccnxContentObjectFacadeV1_GetPayloadType(contentObjectDictionary) != payloadType) {
+ ccnxTlvDictionary_PutInteger(contentObjectDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE, payloadType);
+ }
+
+ if (originalPayload != NULL) {
+ parcBuffer_Release(&originalPayload);
+ }
+ }
+ }
+
+ return result;
+}
+
+// =========================
+// Miscellaneous functions
+
+static bool
+_ccnxContentObjectFacadeV1_Equals(const CCNxTlvDictionary *objectA, const CCNxTlvDictionary *objectB)
+{
+ return ccnxTlvDictionary_Equals(objectA, objectB);
+}
+
+static char *
+_ccnxContentObjectFacadeV1_ToString(const CCNxTlvDictionary *contentObjectDictionary)
+{
+ trapNotImplemented("_ccnxContentObjectFacadeV1_ToString(): not yet implemented");
+}
+
+static void
+_ccnxContentObjectFacadeV1_Display(const CCNxTlvDictionary *contentObjectDictionary, size_t indentation)
+{
+ _assertInvariants(contentObjectDictionary);
+ ccnxTlvDictionary_Display(contentObjectDictionary, (unsigned) indentation);
+}
+
+/**
+ * `CCNxContentObjectFacadeV1_Implementation` is the structure containing the pointers to the
+ * V1 schema ContentObject implementation.
+ */
+CCNxContentObjectInterface CCNxContentObjectFacadeV1_Implementation = {
+ .description = "CCNxContentObjectFacadeV1_Implementation",
+
+ .createWithNameAndPayload = &_ccnxContentObjectFacadeV1_CreateWithNameAndPayload,
+ .createWithPayload = &_ccnxContentObjectFacadeV1_CreateWithPayload,
+
+ .setSignature = &_ccnxContentObjectFacadeV1_SetSignature,
+ .getKeyId = &_ccnxContentObjectFacadeV1_GetKeyId,
+
+ .getName = &_ccnxContentObjectFacadeV1_GetName,
+ .getPayload = &_ccnxContentObjectFacadeV1_GetPayload,
+ .setPayload = &_ccnxContentObjectFacadeV1_SetPayload,
+ .getPayloadType = &_ccnxContentObjectFacadeV1_GetPayloadType,
+
+ .getFinalChunkNumber = &ccnxChunkingFacadeV1_GetEndChunkNumber,
+ .setFinalChunkNumber = &ccnxChunkingFacadeV1_SetEndChunkNumber,
+ .hasFinalChunkNumber = &ccnxChunkingFacadeV1_HasEndChunkNumber,
+
+ .getExpiryTime = &_ccnxContentObjectFacadeV1_GetExpiryTime,
+ .setExpiryTime = &_ccnxContentObjectFacadeV1_SetExpiryTime,
+ .hasExpiryTime = &_ccnxContentObjectFacadeV1_HasExpiryTime,
+
+ .getPathLabel = &_ccnxContentObjectFacadeV1_GetPathLabel,
+ .setPathLabel = &_ccnxContentObjectFacadeV1_SetPathLabel,
+ .hasPathLabel = &_ccnxContentObjectFacadeV1_HasPathLabel,
+
+ .toString = &_ccnxContentObjectFacadeV1_ToString,
+ .display = &_ccnxContentObjectFacadeV1_Display,
+ .equals = &_ccnxContentObjectFacadeV1_Equals,
+
+ .assertValid = &_assertInvariants,
+};
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ContentObjectFacadeV1.h b/libccnx-common/ccnx/common/internal/ccnx_ContentObjectFacadeV1.h
new file mode 100755
index 00000000..d95c56b3
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ContentObjectFacadeV1.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ccnx_ContentObjectFacade.h
+ * @ingroup ContentObject
+ * @brief This facade is used to access fields within an RTA-encoded content object.
+ *
+ * Content objects are encoded and transmitted through the transport stack before being sent over the wire.
+ * This facade acts an interface to this transport-specific encoding of the content object. It enables
+ * the user to directly access fields within the content object without having any knowledge about the
+ * particular schema-specific encoding.
+ *
+ */
+#ifndef libccnx_ccnx_ContentObjectFacadeV1_h
+#define libccnx_ccnx_ContentObjectFacadeV1_h
+
+#include <ccnx/common/internal/ccnx_ContentObjectInterface.h>
+
+extern CCNxContentObjectInterface CCNxContentObjectFacadeV1_Implementation;
+
+#endif // libccnx_ccnx_ContentObjectFacadeV1_h
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ContentObjectInterface.c b/libccnx-common/ccnx/common/internal/ccnx_ContentObjectInterface.c
new file mode 100755
index 00000000..ac33c2ab
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ContentObjectInterface.c
@@ -0,0 +1,54 @@
+/*
+ * 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 <config.h>
+
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/internal/ccnx_ContentObjectInterface.h>
+
+
+CCNxContentObjectInterface *
+ccnxContentObjectInterface_GetInterface(const CCNxTlvDictionary *dictionary)
+{
+ assertTrue(ccnxTlvDictionary_IsContentObject(dictionary), "Expected a ContentObject");
+
+ CCNxContentObjectInterface *impl = (CCNxContentObjectInterface *) ccnxTlvDictionary_GetMessageInterface(dictionary);
+
+ if (impl == NULL) {
+ // If we're here, we need to update the implementation pointer.
+ // Figure out what the typeImplementation should be, based on the attributes we know.
+ int schemaVersion = ccnxTlvDictionary_GetSchemaVersion(dictionary);
+
+ switch (schemaVersion) {
+ case CCNxTlvDictionary_SchemaVersion_V1:
+ impl = &CCNxContentObjectFacadeV1_Implementation;
+ break;
+ default:
+ trapUnexpectedState("Unknown SchemaVersion encountered in ccnxContentObjectInterface_GetInterface()");
+ break;
+ }
+
+ if (impl != NULL) {
+ // The cast to (CCNxTlvDictionary *) is to break the const.
+ ccnxTlvDictionary_SetMessageInterface((CCNxTlvDictionary *) dictionary, (CCNxMessageInterface *) impl);
+ }
+ }
+
+ return impl;
+}
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ContentObjectInterface.h b/libccnx-common/ccnx/common/internal/ccnx_ContentObjectInterface.h
new file mode 100644
index 00000000..c2d67680
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ContentObjectInterface.h
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+/**
+ * @brief A structure of functions representing a ContentObject implementation.
+ *
+ * The underlying implementation should support the CCNxContentObject API.
+ *
+ */
+
+#ifndef CCNx_Common_ccnx_internal_ContentObjectInterface_h
+#define CCNx_Common_ccnx_internal_ContentObjectInterface_h
+
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+
+#include <ccnx/common/ccnx_Name.h>
+#include <ccnx/common/ccnx_KeyLocator.h>
+#include <ccnx/common/ccnx_PayloadType.h>
+
+typedef struct ccnx_contentobject_interface {
+ char *description; // A human-readable label for this implementation
+
+ /** @see ccnxContentObject_CreateWithNameAndPayload */
+ CCNxTlvDictionary *(*createWithNameAndPayload)(const CCNxName * contentName,
+ const CCNxPayloadType contentType,
+ const PARCBuffer * payload);
+
+ /** @see ccnxContentObject_CreateWithPayload */
+ CCNxTlvDictionary *(*createWithPayload)(const CCNxPayloadType contentType,
+ const PARCBuffer * payload);
+
+ /** @see ccnxContentObject_GetName */
+ CCNxName *(*getName)(const CCNxTlvDictionary * dict);
+
+ /** @see ccnxContentObject_SetSignature */
+ bool (*setSignature)(CCNxTlvDictionary *dict,
+ const PARCBuffer *keyId,
+ const PARCSignature *signature,
+ const CCNxKeyLocator *keyLocator);
+
+ /** @see ccnxContentObject_GetKeyId */
+ PARCBuffer *(*getKeyId)(const CCNxTlvDictionary * dict);
+
+ /** @see ccnxContentObject_GetPayload */
+ PARCBuffer *(*getPayload)(const CCNxTlvDictionary * dict);
+
+ /** @see ccnxContentObject_GetPayloadType */
+ CCNxPayloadType (*getPayloadType)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxContentObject_SetPayload */
+ bool (*setPayload)(CCNxTlvDictionary *dict, CCNxPayloadType payloadType, const PARCBuffer *payload);
+
+ /** @see ccnxContentObject_SetFinalChunkNumber */
+ bool (*setFinalChunkNumber)(CCNxTlvDictionary *dict, const uint64_t finalChunkNumber);
+
+ /** @see ccnxContentObject_GetFinalChunkNumber */
+ uint64_t (*getFinalChunkNumber)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxContentObject_HasFinalChunkNumber */
+ bool (*hasFinalChunkNumber)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxContentObject_SetExpiryTime */
+ bool (*setExpiryTime)(CCNxTlvDictionary *dict, const uint64_t expiryTime);
+
+ /** @see ccnxContentObject_GetExpiryTime */
+ uint64_t (*getExpiryTime)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxContentObject_HasExpiryTime */
+ bool (*hasExpiryTime)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxContentObject_Equals */
+ bool (*equals)(const CCNxTlvDictionary *objectA, const CCNxTlvDictionary *objectB);
+
+ /** @see ccnxContentObject_AssertValid */
+ void (*assertValid)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxContentObject_ToString */
+ char *(*toString)(const CCNxTlvDictionary * dict);
+
+ /** @see ccnxContentObject_CreateWithPayload */
+ void (*display)(const CCNxTlvDictionary *interestDictionary, size_t indentation);
+
+ bool (*setPathLabel)(CCNxTlvDictionary *dict, const uint64_t pathLabel);
+ uint64_t (*getPathLabel)(const CCNxTlvDictionary *dict);
+ bool (*hasPathLabel)(const CCNxTlvDictionary *dict);
+} CCNxContentObjectInterface;
+
+/**
+ * The SchemaV1 ContentObject implementaton
+ */
+extern CCNxContentObjectInterface CCNxContentObjectFacadeV1_Implementation;
+
+/**
+ * Given a CCNxTlvDictionary representing a CCNxContentObject, return the address of the CCNxContentObjectInterface
+ * instance that should be used to access the ContentObject. This will also update the CCNxTlvDictionary's implementation
+ * pointer for future references.
+ *
+ * @param contentDictionary - a {@link CCNxTlvDictionary} representing a CCNxContentObject.
+ * @return the address of the `CCNxContentObjectInterface` instance that should be used to access the CCNxContentObject.
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+ *
+ * CCNxContentObject *contentObjectV0 =
+ * ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV0_Implementation,
+ * name,
+ * CCNxPayloadType_DATA,
+ * NULL);
+ *
+ * CCNxContentObject *contentObjectV1 =
+ * ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ * name,
+ * CCNxPayloadType_DATA,
+ * NULL);
+ *
+ * assertTrue(ccnxContentObjectInterface_GetInterface(contentObjectV0) == &CCNxContentObjectFacadeV0_Implementation,
+ * "Expected V0 Implementation");
+ *
+ * assertTrue(ccnxContentObjectInterface_GetInterface(contentObjectV1) == &CCNxContentObjectFacadeV1_Implementation,
+ * "Expected V1 Implementation");
+ *
+ * ccnxName_Release(&name);
+ * ccnxContentObject_Release(&contentObjectV0);
+ * ccnxContentObject_Release(&contentObjectV1);
+ * }
+ * @endcode
+ */
+CCNxContentObjectInterface *ccnxContentObjectInterface_GetInterface(const CCNxTlvDictionary *contentDictionary);
+#endif
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestDefault.c b/libccnx-common/ccnx/common/internal/ccnx_InterestDefault.c
new file mode 100755
index 00000000..a0bb134a
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestDefault.c
@@ -0,0 +1,24 @@
+/*
+ * 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 "ccnx_InterestDefault.h"
+
+const uint32_t CCNxInterestDefault_LifetimeMilliseconds = -1;
+const uint32_t CCNxInterestDefault_HopLimit = 255;
+const CCNxInterestPayloadIdMethod CCNxInterestDefault_PayloadIdMethod = CCNxInterestPayloadIdMethod_App;
+
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestDefault.h b/libccnx-common/ccnx/common/internal/ccnx_InterestDefault.h
new file mode 100755
index 00000000..ebfc859a
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestDefault.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ccnx_InterestDefault.h
+ * @brief Default values for various fields in an Interest
+ *
+ * Declares several constants that may be used when creating an Interest with default values.
+ * These may be used in a V0 or V1 Interest.
+ *
+ */
+
+#ifndef __CCNx_Common__ccnx_InterestDefault__
+#define __CCNx_Common__ccnx_InterestDefault__
+
+#include <inttypes.h>
+#include <ccnx/common/internal/ccnx_InterestPayloadIdMethod.h>
+
+/**
+ * May be used in calls to create an Interest with the default lifetime. An Interest with
+ * the default lifetime does not encode the field in the wire format.
+ */
+extern const uint32_t CCNxInterestDefault_LifetimeMilliseconds;
+
+/**
+ * May be used in calls to create an Interest with the default hoplimit.
+ */
+extern const uint32_t CCNxInterestDefault_HopLimit;
+
+/**
+ * May be used in calls to create an Interest with the default payload id method.
+ *
+ * The PayloadIdMethod is a field inside the Interest that describes how the InterestPayloadId in the Name
+ * was calcuated.
+ */
+extern const CCNxInterestPayloadIdMethod CCNxInterestDefault_PayloadIdMethod;
+
+#endif /* defined(__CCNx_Common__ccnx_InterestDefault__) */
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestFacadeV1.c b/libccnx-common/ccnx/common/internal/ccnx_InterestFacadeV1.c
new file mode 100644
index 00000000..5fca3cea
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestFacadeV1.c
@@ -0,0 +1,295 @@
+/*
+ * 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/internal/ccnx_InterestFacadeV1.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+#include <ccnx/common/internal/ccnx_InterestDefault.h>
+
+
+// =====================
+
+static void
+_assertInvariants(const CCNxTlvDictionary *interestDictionary)
+{
+ assertNotNull(interestDictionary, "Dictionary is null");
+ assertTrue((ccnxTlvDictionary_IsInterest(interestDictionary) ||
+ ccnxTlvDictionary_IsInterestReturn(interestDictionary)), "Dictionary is not an interest");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(interestDictionary) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Dictionary is wrong schema Interest, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(interestDictionary), CCNxTlvDictionary_SchemaVersion_V1);
+}
+
+static uint32_t
+_fetchUint32(const CCNxTlvDictionary *interestDictionary, uint32_t key, uint32_t defaultValue)
+{
+ if (ccnxTlvDictionary_IsValueInteger(interestDictionary, key)) {
+ return (uint32_t) ccnxTlvDictionary_GetInteger(interestDictionary, key);
+ }
+ return defaultValue;
+}
+
+static bool
+_ccnxInterestFacadeV1_SetContentObjectHashRestriction(CCNxTlvDictionary *interestDictionary, const PARCBuffer *contentObjectHash)
+{
+ _assertInvariants(interestDictionary);
+ PARCCryptoHash *hash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, contentObjectHash);
+ bool result = ccnxTlvDictionary_PutObject(interestDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION,
+ hash);
+ parcCryptoHash_Release(&hash);
+ return result;
+}
+
+// forward declaration. Body below, in Getters.
+static CCNxName *
+_ccnxInterestFacadeV1_GetName(const CCNxTlvDictionary *interestDictionary);
+
+static bool
+_ccnxInterestFacadeV1_SetPayloadWithId(CCNxTlvDictionary *interestDictionary, const PARCBuffer *payload, const CCNxInterestPayloadId *payloadId)
+{
+ bool result = false;
+
+ if (payload) {
+ result = ccnxTlvDictionary_PutBuffer(interestDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, payload);
+ if (payloadId != NULL) {
+ CCNxName *name = _ccnxInterestFacadeV1_GetName(interestDictionary);
+ ccnxName_Append(name, ccnxInterestPayloadId_GetNameSegment(payloadId));
+ }
+ }
+ return result;
+}
+
+static bool
+_ccnxInterestFacadeV1_SetPayloadAndId(CCNxTlvDictionary *interestDictionary, const PARCBuffer *payload)
+{
+ bool result = false;
+
+ if (payload) {
+ CCNxInterestPayloadId *pid = ccnxInterestPayloadId_CreateAsSHA256Hash(payload);
+ _ccnxInterestFacadeV1_SetPayloadWithId(interestDictionary, payload, pid);
+ ccnxInterestPayloadId_Release(&pid);
+ }
+ return result;
+}
+
+static bool
+_ccnxInterestFacadeV1_SetPayload(CCNxTlvDictionary *interestDictionary, const PARCBuffer *payload)
+{
+ bool result = false;
+
+ if (payload) {
+ _ccnxInterestFacadeV1_SetPayloadWithId(interestDictionary, payload, NULL);
+ }
+ return result;
+}
+
+static bool
+_ccnxInterestFacadeV1_SetLifetime(CCNxTlvDictionary *interestDictionary, uint32_t lifetimeInMillis)
+{
+ return ccnxTlvDictionary_PutInteger(interestDictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime, lifetimeInMillis);
+}
+
+static bool
+_ccnxInterestFacadeV1_SetKeyIdRestriction(CCNxTlvDictionary *interestDictionary, const PARCBuffer *keyId)
+{
+ _assertInvariants(interestDictionary);
+ PARCCryptoHash *hash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, keyId);
+ bool result = ccnxTlvDictionary_PutObject(interestDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION, hash);
+ parcCryptoHash_Release(&hash);
+ return result;
+}
+
+static bool
+_ccnxInterestFacadeV1_SetHopLimit(CCNxTlvDictionary *interestDictionary, uint32_t hopLimit)
+{
+ _assertInvariants(interestDictionary);
+ return ccnxTlvDictionary_PutInteger(interestDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT, hopLimit);
+}
+
+// =====================
+// Getters
+
+static CCNxName *
+_ccnxInterestFacadeV1_GetName(const CCNxTlvDictionary *interestDictionary)
+{
+ int key = CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME;
+ _assertInvariants(interestDictionary);
+ if (ccnxTlvDictionary_IsValueName(interestDictionary, key)) {
+ return ccnxTlvDictionary_GetName(interestDictionary, key);
+ }
+ return NULL;
+}
+
+static uint32_t
+_ccnxInterestFacadeV1_GetLifetime(const CCNxTlvDictionary *interestDictionary)
+{
+ _assertInvariants(interestDictionary);
+ return _fetchUint32(interestDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime, CCNxInterestDefault_LifetimeMilliseconds);
+}
+
+static PARCBuffer *
+_ccnxInterestFacadeV1_GetKeyIdRestriction(const CCNxTlvDictionary *interestDictionary)
+{
+ _assertInvariants(interestDictionary);
+ PARCCryptoHash *hash = ccnxTlvDictionary_GetObject(interestDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION);
+ if (hash != NULL) {
+ return parcCryptoHash_GetDigest(hash);
+ } else {
+ return NULL;
+ }
+}
+
+static PARCBuffer *
+_ccnxInterestFacadeV1_GetContentObjectHashRestriction(const CCNxTlvDictionary *interestDictionary)
+{
+ _assertInvariants(interestDictionary);
+ PARCCryptoHash *hash = ccnxTlvDictionary_GetObject(interestDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION);
+ if (hash != NULL) {
+ return parcCryptoHash_GetDigest(hash);
+ } else {
+ return NULL;
+ }
+}
+
+static PARCBuffer *
+_ccnxInterestFacadeV1_GetPayload(const CCNxTlvDictionary *interestDictionary)
+{
+ _assertInvariants(interestDictionary);
+ return ccnxTlvDictionary_GetBuffer(interestDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD);
+}
+
+static uint32_t
+_ccnxInterestFacadeV1_GetHopLimit(const CCNxTlvDictionary *interestDictionary)
+{
+ _assertInvariants(interestDictionary);
+ return _fetchUint32(interestDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT, CCNxInterestDefault_HopLimit);
+}
+
+// =====================
+// Miscellaneous
+
+static void
+_ccnxInterestFacadeV1_AssertValid(const CCNxTlvDictionary *interestDictionary)
+{
+ _assertInvariants(interestDictionary);
+ assertTrue(ccnxTlvDictionary_IsValueName(interestDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME), "Name field is not a name");
+}
+
+static bool
+_ccnxInterestFacadeV1_Equals(const CCNxTlvDictionary *a, const CCNxTlvDictionary *b)
+{
+ return ccnxTlvDictionary_Equals(a, b);
+}
+
+static void
+_ccnxInterestFacadeV1_Display(const CCNxTlvDictionary *interestDictionary, size_t indentation)
+{
+ _assertInvariants(interestDictionary);
+ ccnxTlvDictionary_Display(interestDictionary, (unsigned) indentation);
+}
+
+
+// =====================
+// Creation
+
+static CCNxTlvDictionary *
+_ccnxInterestFacadeV1_Create(const CCNxName *name, // required
+ const uint32_t lifetimeMilliseconds, // may use DefaultLimetimeMilliseconds
+ const PARCBuffer *keyId, // may be NULL
+ const PARCBuffer *contentObjectHash, // may be NULL
+ const uint32_t hopLimit) // may be DefaultHopLimit
+{
+ assertNotNull(name, "Parameter name must be non-null");
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ if (dictionary) {
+ ccnxTlvDictionary_PutName(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME, name);
+
+ if (lifetimeMilliseconds != CCNxInterestDefault_LifetimeMilliseconds) {
+ _ccnxInterestFacadeV1_SetLifetime(dictionary, lifetimeMilliseconds);
+ }
+
+ if (keyId) {
+ _ccnxInterestFacadeV1_SetKeyIdRestriction(dictionary, keyId);
+ }
+
+ if (contentObjectHash) {
+ _ccnxInterestFacadeV1_SetContentObjectHashRestriction(dictionary, contentObjectHash);
+ }
+
+ if (hopLimit != CCNxInterestDefault_HopLimit) {
+ _ccnxInterestFacadeV1_SetHopLimit(dictionary, hopLimit);
+ }
+ } else {
+ trapOutOfMemory("Could not allocate an Interest");
+ }
+
+ return dictionary;
+}
+
+static CCNxTlvDictionary *
+_ccnxInterestFacadeV1_CreateSimple(const CCNxName *name)
+{
+ return _ccnxInterestFacadeV1_Create(name,
+ CCNxInterestDefault_LifetimeMilliseconds,
+ NULL, // keyid
+ NULL, // content object hash
+ CCNxInterestDefault_HopLimit);
+}
+
+CCNxInterestInterface CCNxInterestFacadeV1_Implementation = {
+ .description = "CCNxInterestFacadeV1_Implementation",
+
+ .createSimple = &_ccnxInterestFacadeV1_CreateSimple,
+ .create = &_ccnxInterestFacadeV1_Create,
+
+ .getName = &_ccnxInterestFacadeV1_GetName,
+
+ .setContentObjectHashRestriction = &_ccnxInterestFacadeV1_SetContentObjectHashRestriction,
+ .getContentObjectHashRestriction = &_ccnxInterestFacadeV1_GetContentObjectHashRestriction,
+
+ .setLifetime = &_ccnxInterestFacadeV1_SetLifetime,
+ .getLifetime = &_ccnxInterestFacadeV1_GetLifetime,
+
+ .setKeyIdRestriction = &_ccnxInterestFacadeV1_SetKeyIdRestriction,
+ .getKeyIdRestriction = &_ccnxInterestFacadeV1_GetKeyIdRestriction,
+
+ .getHopLimit = &_ccnxInterestFacadeV1_GetHopLimit,
+ .setHopLimit = &_ccnxInterestFacadeV1_SetHopLimit,
+
+ .getPayload = &_ccnxInterestFacadeV1_GetPayload,
+
+ .setPayload = &_ccnxInterestFacadeV1_SetPayload,
+ .setPayloadAndId = &_ccnxInterestFacadeV1_SetPayloadAndId,
+ .setPayloadWithId = &_ccnxInterestFacadeV1_SetPayloadWithId,
+
+ .toString = NULL,
+ .equals = &_ccnxInterestFacadeV1_Equals,
+ .display = &_ccnxInterestFacadeV1_Display,
+
+ .assertValid = &_ccnxInterestFacadeV1_AssertValid,
+};
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestFacadeV1.h b/libccnx-common/ccnx/common/internal/ccnx_InterestFacadeV1.h
new file mode 100755
index 00000000..29739f2c
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestFacadeV1.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ccnx_InterestFacadeV1.h
+ * @ingroup Interest
+ * @brief A CCN Interest facade for an Interest over a CCNxTlvDictionary, using v1 schema.
+ *
+ */
+#ifndef libccnx_ccnx_InterestFacadeV1_h
+#define libccnx_ccnx_InterestFacadeV1_h
+
+#include <ccnx/common/internal/ccnx_InterestInterface.h>
+
+extern CCNxInterestInterface CCNxInterestFacadeV1_Implementation;
+
+#endif // libccnx_ccnx_InterestFacadeV1_h
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestInterface.c b/libccnx-common/ccnx/common/internal/ccnx_InterestInterface.c
new file mode 100755
index 00000000..a507d69d
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestInterface.c
@@ -0,0 +1,53 @@
+/*
+ * 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 <config.h>
+
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/internal/ccnx_InterestInterface.h>
+
+CCNxInterestInterface *
+ccnxInterestInterface_GetInterface(const CCNxTlvDictionary *dictionary)
+{
+ assertTrue((ccnxTlvDictionary_IsInterest(dictionary) ||
+ ccnxTlvDictionary_IsInterestReturn(dictionary)), "Expected an Interest or InterestReturn");
+
+ CCNxInterestInterface *impl = (CCNxInterestInterface *) ccnxTlvDictionary_GetMessageInterface(dictionary);
+
+ if (impl == NULL) {
+ // If we're here, we need to update the interface pointer.
+ // Figure out what the typeInterface should be, based on the attributes we know.
+ int schemaVersion = ccnxTlvDictionary_GetSchemaVersion(dictionary);
+
+ switch (schemaVersion) {
+ case CCNxTlvDictionary_SchemaVersion_V1:
+ impl = &CCNxInterestFacadeV1_Implementation;
+ break;
+ default:
+ trapUnexpectedState("Unknown SchemaVersion encountered in ccnxInterestInterface_GetInterface()");
+ break;
+ }
+
+ if (impl == NULL) {
+ // The cast to (CCNxTlvDictionary *) is to break the const.
+ ccnxTlvDictionary_SetMessageInterface((CCNxTlvDictionary *) dictionary, (CCNxMessageInterface *) impl);
+ }
+ }
+ return impl;
+}
+
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestInterface.h b/libccnx-common/ccnx/common/internal/ccnx_InterestInterface.h
new file mode 100644
index 00000000..bb78dfc3
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestInterface.h
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+/**
+ * @brief A structure of functions representing an Interest implementation.
+ *
+ * The underlying implementation should support the CCNxInterest API.
+ *
+ */
+
+#ifndef CCNx_Common_ccnx_internal_InterestInterface_h
+#define CCNx_Common_ccnx_internal_InterestInterface_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+
+#include <ccnx/common/internal/ccnx_InterestPayloadIdMethod.h>
+#include <ccnx/common/ccnx_InterestPayloadId.h>
+
+typedef struct ccnx_interest_interface {
+ /** A human-readable label for this implementation */
+ char *description;
+
+ /** @see ccnxInterest_Create */
+ CCNxTlvDictionary *(*create)(const CCNxName * name, // required
+ const uint32_t lifetimeMilliseconds, // may use DefaultLimetimeMilliseconds
+ const PARCBuffer * keyId, // may be NULL
+ const PARCBuffer * contentObjectHash, // may be NULL
+ const uint32_t hopLimit);
+
+ /** @see ccnxInterest_CreateSimple */
+ CCNxTlvDictionary *(*createSimple)(const CCNxName * name);
+
+ /** @see ccnxInterest_GetName */
+ CCNxName *(*getName)(const CCNxTlvDictionary * dict);
+
+ /** @see ccnxInterest_SetLifetime */
+ bool (*setLifetime)(CCNxTlvDictionary *dict, uint32_t lifetime);
+
+ /** @see ccnxInterest_GetLifetime */
+ uint32_t (*getLifetime)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxInterest_SetHopLimit */
+ bool (*setHopLimit)(CCNxTlvDictionary *dict, uint32_t hopLimit);
+
+ /** @see ccnxInterest_GetHopLimit */
+ uint32_t (*getHopLimit)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxInterest_SetKeyIdRestriction */
+ bool (*setKeyIdRestriction)(CCNxTlvDictionary *dict, const PARCBuffer *keyId);
+
+ /** @see ccnxInterest_GetKeyIdRestriction */
+ PARCBuffer *(*getKeyIdRestriction)(const CCNxTlvDictionary * dict);
+
+ /** @see ccnxInterest_SetPayload */
+ bool (*setPayload)(CCNxTlvDictionary *dict, const PARCBuffer *payload);
+
+ /** @see ccnxInterest_SetPayloadAndId */
+ bool (*setPayloadAndId)(CCNxTlvDictionary *dict, const PARCBuffer *payload);
+
+ /** @see ccnxInterest_SetPayloadWithId */
+ bool (*setPayloadWithId)(CCNxTlvDictionary *dict, const PARCBuffer *payload, const CCNxInterestPayloadId *id);
+
+ /** @see ccnxInterest_GetPayload */
+ PARCBuffer *(*getPayload)(const CCNxTlvDictionary * dict);
+
+ /** @see ccnxInterest_SetContentObjectHashRestriction */
+ bool (*setContentObjectHashRestriction)(CCNxTlvDictionary *dict, const PARCBuffer *contentObjectHash);
+
+ /** @see ccnxInterest_GetContentObjectHashRestriction */
+ PARCBuffer *(*getContentObjectHashRestriction)(const CCNxTlvDictionary * dict);
+
+ /** @see ccnxInterest_Equals */
+ bool (*equals)(const CCNxTlvDictionary *objectA, const CCNxTlvDictionary *objectB);
+ /** @see ccnxInterest_AssertValid */
+ void (*assertValid)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxInterest_ToString */
+ char *(*toString)(const CCNxTlvDictionary * dict);
+ /** @see ccnxInterest_Display */
+ void (*display)(const CCNxTlvDictionary *interestDictionary, size_t indentation);
+} CCNxInterestInterface;
+
+
+/**
+ * The SchemaV1 Interest implementaton
+ */
+extern CCNxInterestInterface CCNxInterestFacadeV1_Implementation;
+
+/**
+ * Given a CCNxTlvDictionary representing a CCNxInterest, return the address of the CCNxInterestInterface
+ * instance that should be used to access the Interest. This will also update the CCNxTlvDictionary's interface
+ * pointer for future references.
+ *
+ * @param interestDictionary - a {@link CCNxTlvDictionary} representing a CCNxInterest.
+ * @return the address of the `CCNxContentObjectInterface` instance that should be used to access the CCNxInterest.
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+ *
+ * CCNxInterest *interestV1 =
+ * ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ * name,
+ * CCNxInterestDefault_LifetimeMilliseconds,
+ * NULL,
+ * NULL,
+ * CCNxInterestDefault_HopLimit);
+ *
+ * assertTrue(ccnxInterestInterface_GetInterface(interestV1) == &CCNxInterestFacadeV1_Implementation,
+ * "Expected V1 Implementation");
+ *
+ * ccnxName_Release(&name);
+ * ccnxInterest_Release(&interestV1);
+ * } * @endcode
+ */
+CCNxInterestInterface *ccnxInterestInterface_GetInterface(const CCNxTlvDictionary *interestDictionary);
+#endif
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestPayloadIdMethod.h b/libccnx-common/ccnx/common/internal/ccnx_InterestPayloadIdMethod.h
new file mode 100755
index 00000000..a29ddb9e
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestPayloadIdMethod.h
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/**
+ */
+
+#ifndef CCNx_Common_ccnx_InterestPayloadIdMethod_h
+#define CCNx_Common_ccnx_InterestPayloadIdMethod_h
+
+typedef enum {
+ CCNxInterestPayloadIdMethod_App = 0,
+ CCNxInterestPayloadIdMethod_Nonce = 1,
+ CCNxInterestPayloadIdMethod_RFC6920 = 2
+} CCNxInterestPayloadIdMethod;
+
+#endif
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestReturnFacadeV1.c b/libccnx-common/ccnx/common/internal/ccnx_InterestReturnFacadeV1.c
new file mode 100755
index 00000000..80c1b718
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestReturnFacadeV1.c
@@ -0,0 +1,100 @@
+/*
+ * 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/internal/ccnx_InterestReturnFacadeV1.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+// =====================
+
+static void
+_assertInvariants(const CCNxTlvDictionary *interestDictionary)
+{
+ assertNotNull(interestDictionary, "Dictionary is null");
+ assertTrue(ccnxTlvDictionary_IsInterestReturn(interestDictionary), "Dictionary is not an interest");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(interestDictionary) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Dictionary is wrong schema InterestReturn, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(interestDictionary), CCNxTlvDictionary_SchemaVersion_V1);
+}
+
+static uint32_t
+_fetchUint32(const CCNxTlvDictionary *interestDictionary, uint32_t key, uint32_t defaultValue)
+{
+ if (ccnxTlvDictionary_IsValueInteger(interestDictionary, key)) {
+ return (uint32_t) ccnxTlvDictionary_GetInteger(interestDictionary, key);
+ }
+ return defaultValue;
+}
+
+// =====================
+// Creation
+
+static CCNxTlvDictionary *
+_ccnxInterestReturnFacadeV1_Create(
+ const CCNxInterest *interest,
+ CCNxInterestReturn_ReturnCode code)
+{
+ assertNotNull(interest, "Parameter name must be non-null");
+
+ assertTrue(ccnxInterestInterface_GetInterface(interest) == &CCNxInterestFacadeV1_Implementation,
+ "Non-V1 CCNxInterest passed to V1 ccnxInterestReturn_Create()");
+
+ CCNxInterestReturnFacadeV1_Implementation.interestImpl = CCNxInterestFacadeV1_Implementation;
+
+
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_ShallowCopy(interest);
+
+ //Add InterestReturn specific stuff
+ ccnxTlvDictionary_SetMessageType_InterestReturn(dictionary,
+ CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_PutInteger(dictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestReturnCode,
+ code);
+
+ return dictionary;
+}
+
+static void
+_ccnxInterestReturnFacadeV1_AssertValid(const CCNxTlvDictionary *interestDictionary)
+{
+ _assertInvariants(interestDictionary);
+ assertTrue(ccnxTlvDictionary_IsValueName(interestDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME), "Name field is not a name");
+}
+
+static CCNxInterestReturn_ReturnCode
+_ccnxInterestReturnFacadeV1_GetReturnCode(const CCNxTlvDictionary *interestDictionary)
+{
+ _assertInvariants(interestDictionary);
+ CCNxInterestReturn_ReturnCode code = _fetchUint32(interestDictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestReturnCode,
+ 0);
+ assertTrue(((code > 0) && (code < CCNxInterestReturn_ReturnCode_END)), "InterestReturn ReturnCode is out of ranage");
+
+ return code;
+}
+
+CCNxInterestReturnInterface CCNxInterestReturnFacadeV1_Implementation = {
+ .Create = &_ccnxInterestReturnFacadeV1_Create,
+ .AssertValid = &_ccnxInterestReturnFacadeV1_AssertValid,
+ .GetReturnCode = &_ccnxInterestReturnFacadeV1_GetReturnCode,
+};
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestReturnFacadeV1.h b/libccnx-common/ccnx/common/internal/ccnx_InterestReturnFacadeV1.h
new file mode 100755
index 00000000..e8aa0e37
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestReturnFacadeV1.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ccnx_InterestReturnFacadeV1.h
+ * @ingroup InterestReturn
+ * @brief A CCN InterestReturn facade over a CCNxTlvDictionary, using v1 schema.
+ *
+ */
+#ifndef libccnx_ccnx_InterestReturnFacadeV1_h
+#define libccnx_ccnx_InterestReturnFacadeV1_h
+
+#include <ccnx/common/internal/ccnx_InterestReturnInterface.h>
+
+extern CCNxInterestReturnInterface CCNxInterestReturnFacadeV1_Implementation;
+
+#endif // libccnx_ccnx_InterestReturnFacadeV1_h
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestReturnInterface.c b/libccnx-common/ccnx/common/internal/ccnx_InterestReturnInterface.c
new file mode 100755
index 00000000..2c9aa111
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestReturnInterface.c
@@ -0,0 +1,55 @@
+/*
+ * 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 <config.h>
+#include <ccnx/common/internal/ccnx_InterestReturnInterface.h>
+
+#include <LongBow/runtime.h>
+
+CCNxInterestReturnInterface *
+ccnxInterestReturnInterface_GetInterface(const CCNxTlvDictionary *dictionary)
+{
+ assertTrue(ccnxTlvDictionary_IsInterestReturn(dictionary), "Expected an InterestReturn");
+
+ CCNxInterestReturnInterface *impl = ccnxTlvDictionary_GetMessageInterface(dictionary);
+
+ if (!impl) {
+ // If we're here, we need to update the interface pointer. Break the const.
+ // We're not changing data values, just initializing the Interface pointer.
+
+ // Figure out what the typeInterface should be, based on the attributes we know.
+ int schemaVersion = ccnxTlvDictionary_GetSchemaVersion(dictionary);
+
+ switch (schemaVersion) {
+ case CCNxTlvDictionary_SchemaVersion_V0:
+ trapUnexpectedState("ccnxInterestReturnInterface_GetInterface() not implemented for V0");
+ case CCNxTlvDictionary_SchemaVersion_V1:
+ impl = &CCNxInterestReturnFacadeV1_Implementation;
+ break;
+ default:
+ trapUnexpectedState("Unknown SchemaVersion encountered in ccnxInterestReturnInterface_GetInterface()");
+ break;
+ }
+
+ if (impl) {
+ ccnxTlvDictionary_SetMessageInterface((CCNxTlvDictionary *) dictionary, impl); // break the const.
+ }
+ }
+
+ return impl;
+}
+
diff --git a/libccnx-common/ccnx/common/internal/ccnx_InterestReturnInterface.h b/libccnx-common/ccnx/common/internal/ccnx_InterestReturnInterface.h
new file mode 100644
index 00000000..3f36fb90
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_InterestReturnInterface.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+/**
+ * @brief <#Brief Description#>
+ *
+ * <#Detailed Description#>
+ *
+ */
+
+#ifndef CCNx_Common_ccnx_internal_InterestReturnInterface_h
+#define CCNx_Common_ccnx_internal_InterestReturnInterface_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/ccnx_InterestReturn.h>
+#include <ccnx/common/ccnx_Interest.h>
+
+
+typedef struct ccnx_interest_return_interface {
+ CCNxInterestInterface interestImpl;
+
+ CCNxTlvDictionary *(*Create)(const CCNxInterest * interest, CCNxInterestReturn_ReturnCode code);
+
+ bool (*Equals)(const CCNxTlvDictionary *objectA, const CCNxTlvDictionary *objectB);
+ void (*AssertValid)(const CCNxTlvDictionary *dict);
+ char *(*ToString)(const CCNxTlvDictionary * dict);
+
+ uint32_t (*GetReturnCode)(const CCNxTlvDictionary *dict);
+} CCNxInterestReturnInterface;
+
+extern CCNxInterestReturnInterface CCNxInterestReturnFacadeV1_Implementation;
+
+/**
+ * Given a CCNxTlvDictionary representing a CCNxInterestReturn, return the address of the CCNxInterestReturnInterface
+ * instance that should be used to access the InterestReturn.
+ *
+ * @param interestDictionary - a {@link CCNxTlvDictionary} representing a CCNxInterestReturn.
+ * @return the address of the `CCNxInterestReturnInterface` instance that should be used to access the CCNxInterestReturn.
+ *
+ * Example:
+ * @code
+ * {
+ *
+ * CCNxInterest *interest = ...;
+ * CCNxInterestReturn *interestReturn =
+ * ccnxInterestReturn_Create(interest, CCNxInterestReturn_ReturnCode_NoRoute);
+ *
+ * //V1 test
+ * if (ccnxInterestReturnInterface_GetInterface(interestReturn) == &CCNxInterestReturnFacadeV1_Implementation) {
+ * printf("Using a V1 CCNxInterestReturnInterface \n");
+ * }
+ *
+ * ...
+ *
+ * ccnxInterestReturn_Release(&interestReturn);
+ * } * @endcode
+ */
+CCNxInterestReturnInterface *ccnxInterestReturnInterface_GetInterface(const CCNxTlvDictionary *interestDictionary);
+#endif
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ManifestFacadeV1.c b/libccnx-common/ccnx/common/internal/ccnx_ManifestFacadeV1.c
new file mode 100644
index 00000000..e419d18e
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ManifestFacadeV1.c
@@ -0,0 +1,132 @@
+/*
+ * 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <LongBow/runtime.h>
+
+#include <parc/algol/parc_JSON.h>
+
+#include <ccnx/common/ccnx_Manifest.h>
+#include <ccnx/common/internal/ccnx_ManifestInterface.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+static size_t _ccnxManifestFacadeV1_GetNumberOfHashGroups(const CCNxTlvDictionary *dict);
+
+static CCNxTlvDictionary *
+_ccnxManifestFacadeV1_Create(const CCNxName *name)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateManifest();
+
+ if (dictionary != NULL) {
+ if (name != NULL) {
+ ccnxTlvDictionary_PutName(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME, name);
+ }
+ } else {
+ trapOutOfMemory("Could not allocate an Manifest");
+ }
+
+ return dictionary;
+}
+
+static const CCNxName *
+_ccnxManifestFacadeV1_GetName(const CCNxTlvDictionary *dict)
+{
+ return ccnxTlvDictionary_GetName(dict, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME);
+}
+
+static void
+_ccnxManifestFacadeV1_AddHashGroup(CCNxTlvDictionary *dict, const CCNxManifestHashGroup *group)
+{
+ PARCJSON *json = ccnxManifestHashGroup_ToJson(group);
+ size_t numGroups = _ccnxManifestFacadeV1_GetNumberOfHashGroups(dict);
+
+ char *jsonString = parcJSON_ToString(json);
+ PARCBuffer *buffer = parcBuffer_AllocateCString(jsonString);
+ parcMemory_Deallocate(&jsonString);
+ parcJSON_Release(&json);
+
+ ccnxTlvDictionary_PutListBuffer(dict, CCNxCodecSchemaV1TlvDictionary_Lists_HASH_GROUP_LIST, (uint32_t) numGroups, buffer);
+ parcBuffer_Release(&buffer);
+}
+
+static CCNxManifestHashGroup *
+_ccnxManifestFacadeV1_GetHashGroup(const CCNxTlvDictionary *dict, size_t index)
+{
+ PARCBuffer *buffer = NULL;
+ uint32_t key;
+ ccnxTlvDictionary_ListGetByPosition(dict, CCNxCodecSchemaV1TlvDictionary_Lists_HASH_GROUP_LIST, index, &buffer, &key);
+
+ char *jsonString = parcBuffer_ToString(buffer);
+ PARCJSON *json = parcJSON_ParseString(jsonString);
+ parcMemory_Deallocate(&jsonString);
+
+ CCNxManifestHashGroup *group = ccnxManifestHashGroup_CreateFromJson(json);
+ parcJSON_Release(&json);
+
+ return group;
+}
+
+static size_t
+_ccnxManifestFacadeV1_GetNumberOfHashGroups(const CCNxTlvDictionary *dict)
+{
+ size_t numHashGroups = ccnxTlvDictionary_ListSize(dict, CCNxCodecSchemaV1TlvDictionary_Lists_HASH_GROUP_LIST);
+ return numHashGroups;
+}
+
+static bool
+_ccnxManifestFacadeV1_Equals(const CCNxTlvDictionary *dictA, const CCNxTlvDictionary *dictB)
+{
+ if (dictA == dictB) {
+ return true;
+ }
+ if (dictA == NULL || dictB == NULL) {
+ return false;
+ }
+
+ if (ccnxName_Equals(_ccnxManifestFacadeV1_GetName(dictA), _ccnxManifestFacadeV1_GetName(dictB))) {
+ if (_ccnxManifestFacadeV1_GetNumberOfHashGroups(dictA) == _ccnxManifestFacadeV1_GetNumberOfHashGroups(dictB)) {
+ for (size_t i = 0; i < _ccnxManifestFacadeV1_GetNumberOfHashGroups(dictA); i++) {
+ CCNxManifestHashGroup *groupA = _ccnxManifestFacadeV1_GetHashGroup(dictA, i);
+ CCNxManifestHashGroup *groupB = _ccnxManifestFacadeV1_GetHashGroup(dictB, i);
+
+ if (!ccnxManifestHashGroup_Equals(groupA, groupB)) {
+ ccnxManifestHashGroup_Release(&groupA);
+ ccnxManifestHashGroup_Release(&groupB);
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+};
+
+CCNxManifestInterface CCNxManifestFacadeV1_Interface = {
+ .description = "CCNxManifestFacadeV1_Implementation",
+ .create = &_ccnxManifestFacadeV1_Create,
+ .getName = &_ccnxManifestFacadeV1_GetName,
+ .addHashGroup = &_ccnxManifestFacadeV1_AddHashGroup,
+ .getHashGroup = &_ccnxManifestFacadeV1_GetHashGroup,
+ .getNumberOfHashGroups = &_ccnxManifestFacadeV1_GetNumberOfHashGroups,
+ .equals = &_ccnxManifestFacadeV1_Equals,
+};
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ManifestFacadeV1.h b/libccnx-common/ccnx/common/internal/ccnx_ManifestFacadeV1.h
new file mode 100755
index 00000000..0b5aab5a
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ManifestFacadeV1.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * @file ccnx_ManifestFacadeV1.h
+ * @ingroup Manifest
+ * @brief A CCN Manifest facade over a CCNxTlvDictionary, using V1 schema.
+ *
+ */
+#ifndef libccnx_ccnx_ManifestFacadeV1_h
+#define libccnx_ccnx_ManifestFacadeV1_h
+
+#include <ccnx/common/internal/ccnx_ManifestInterface.h>
+
+extern CCNxManifestInterface CCNxManifestFacadeV1_Interface;
+
+#endif // libccnx_ccnx_ManifestFacadeV1_h
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ManifestInterface.c b/libccnx-common/ccnx/common/internal/ccnx_ManifestInterface.c
new file mode 100755
index 00000000..581eb93c
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ManifestInterface.c
@@ -0,0 +1,55 @@
+/*
+ * 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 <config.h>
+
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/ccnx_PayloadType.h>
+#include <ccnx/common/internal/ccnx_ManifestInterface.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+CCNxManifestInterface *
+ccnxManifestInterface_GetInterface(const CCNxTlvDictionary *dictionary)
+{
+ assertTrue(ccnxTlvDictionary_IsManifest(dictionary), "Expected a Manifest");
+
+ CCNxManifestInterface *impl = (CCNxManifestInterface *) ccnxTlvDictionary_GetMessageInterface(dictionary);
+
+ if (impl == NULL) {
+ // If we're here, we need to update the implementation pointer.
+ // Figure out what the typeImplementation should be, based on the attributes we know.
+ int schemaVersion = ccnxTlvDictionary_GetSchemaVersion(dictionary);
+
+ switch (schemaVersion) {
+ case CCNxTlvDictionary_SchemaVersion_V1:
+ impl = &CCNxManifestFacadeV1_Interface;
+ break;
+ default:
+ trapUnexpectedState("Unknown SchemaVersion encountered in ccnxInterestImplementation_GetImplementation()");
+ break;
+ }
+
+ if (impl == NULL) {
+ // The cast to (CCNxTlvDictionary *) is to break the const.
+ ccnxTlvDictionary_SetMessageInterface((CCNxTlvDictionary *) dictionary, (CCNxMessageInterface *) impl);
+ }
+ }
+
+ return impl;
+}
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ManifestInterface.h b/libccnx-common/ccnx/common/internal/ccnx_ManifestInterface.h
new file mode 100644
index 00000000..75855b0c
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ManifestInterface.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * @brief A structure of functions representing a Manifest implementation.
+ *
+ * The underlying implementation should support the CCNxManifest API.
+ *
+ */
+
+#ifndef CCNx_Common_ccnx_internal_ManifestImpl_h
+#define CCNx_Common_ccnx_internal_ManifestImpl_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/ccnx_ManifestHashGroup.h>
+#include <ccnx/common/ccnx_Name.h>
+#include <ccnx/common/ccnx_KeyLocator.h>
+
+#include "ccnx_TlvDictionary.h"
+
+typedef struct ccnx_manifest_interface {
+ /** A human-readable label for this implementation */
+ char *description;
+
+ /** @see ccnxManifest_Create */
+ CCNxTlvDictionary *(*create)(const CCNxName * name);
+
+ /** @see ccnxManifest_AddHashGroup */
+ void (*addHashGroup)(CCNxTlvDictionary *dict, const CCNxManifestHashGroup *group);
+
+ /** @see ccnxManifest_GetHashGroup */
+ CCNxManifestHashGroup *(*getHashGroup)(const CCNxTlvDictionary * dict, size_t index);
+
+ /** @see ccnxManifest_GetNumberOfHashGroups */
+ size_t (*getNumberOfHashGroups)(const CCNxTlvDictionary *dict);
+
+ /** @see ccnxManifest_Equals */
+ bool (*equals)(const CCNxTlvDictionary *objectA, const CCNxTlvDictionary *objectB);
+
+ /** @see ccnxManifest_GetName */
+ const CCNxName *(*getName)(const CCNxTlvDictionary * dict);
+} CCNxManifestInterface;
+
+CCNxManifestInterface *ccnxManifestInterface_GetInterface(const CCNxTlvDictionary *dictionary);
+
+/**
+ * The SchemaV1 Manifest implementaton
+ */
+extern CCNxManifestInterface CCNxManifestFacadeV1_Interface;
+
+#endif
diff --git a/libccnx-common/ccnx/common/internal/ccnx_MessageInterface.h b/libccnx-common/ccnx/common/internal/ccnx_MessageInterface.h
new file mode 100755
index 00000000..1f438348
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_MessageInterface.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/**
+ */
+
+#ifndef CCNx_Common_ccnx_MessageInterface_h
+#define CCNx_Common_ccnx_MessageInterface_h
+
+/**
+ * A type to represent the ContentObject/Interest/Control Interface pointer. The CCNxTlvDictionary
+ * maintains one that points to the appropriate interface implementation to reference the data
+ * contained in the CCNxTlvDictionary. For example, it might point to a CCNxContentObjectInterface,
+ * which would enable accessing the CCNxTlvDictionary as a ContentObject.
+ *
+ *
+ * @see CCNxContentObjectInterface
+ * @see CCNxInterestInterface
+ */
+typedef void CCNxMessageInterface;
+#endif
diff --git a/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.c b/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.c
new file mode 100755
index 00000000..3c768529
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.c
@@ -0,0 +1,1022 @@
+/*
+ * 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 <config.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <ccnx/common/ccnx_Name.h>
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+#include <LongBow/runtime.h>
+
+#include <parc/algol/parc_DisplayIndented.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <parc/algol/parc_JSON.h>
+
+#define DEBUG_ALLOCS 0
+
+struct ccnx_tlv_dictionary_entry;
+typedef struct ccnx_tlv_list_entry _CCNxTlvDictionaryListEntry;
+
+typedef enum {
+ CCNxTlvDictionaryType_Unknown,
+ CCNxTlvDictionaryType_Interest,
+ CCNxTlvDictionaryType_ContentObject,
+ CCNxTlvDictionaryType_Control,
+ CCNxTlvDictionaryType_InterestReturn,
+ CCNxTlvDictionaryType_Manifest
+} _CCNxTlvDictionaryType;
+
+// These form a singly linked list
+struct ccnx_tlv_list_entry {
+ _CCNxTlvDictionaryListEntry *next;
+ PARCBuffer *buffer;
+ uint16_t key;
+};
+
+#define ENTRY_UNSET ((int) 0)
+#define ENTRY_BUFFER ((int) 1)
+#define ENTRY_NAME ((int) 2)
+#define ENTRY_INTEGER ((int) 3)
+#define ENTRY_IOVEC ((int) 4)
+#define ENTRY_JSON ((int) 5)
+#define ENTRY_OBJECT ((int) 6)
+
+static struct dictionary_type_string {
+ _CCNxTlvDictionaryType type;
+ const char *string;
+} ccnxTlvDictionaryTypeStrings [] = {
+ { .type = CCNxTlvDictionaryType_Unknown, .string = "Invalid" },
+ { .type = CCNxTlvDictionaryType_Interest, .string = "Interest" },
+ { .type = CCNxTlvDictionaryType_ContentObject, .string = "Content Object" },
+ { .type = CCNxTlvDictionaryType_Control, .string = "Control" },
+ { .type = CCNxTlvDictionaryType_InterestReturn, .string = "InterestReturn" },
+ { .type = CCNxTlvDictionaryType_Manifest, .string = "Manifest" },
+ { .type = UINT32_MAX, .string = NULL },
+};
+
+static struct dictionary_entry_type_string {
+ int type;
+ const char *string;
+} ccnxTlvDictionaryEntryTypeStrings [] = {
+ { .type = ENTRY_UNSET, .string = "Unset" },
+ { .type = ENTRY_BUFFER, .string = "Buffer" },
+ { .type = ENTRY_NAME, .string = "Name" },
+ { .type = ENTRY_INTEGER, .string = "Integer" },
+ { .type = ENTRY_IOVEC, .string = "IoVec" },
+ { .type = ENTRY_JSON, .string = "JSON" },
+ { .type = ENTRY_OBJECT, .string = "Object" },
+ { .type = UINT32_MAX, .string = NULL },
+};
+
+static const char *ccnxTlvDictionaryTypeUnknown = "Unknown";
+
+static const char *
+_ccnxTlvDictionaryEntryTypeToString(int entryType)
+{
+ for (int i = 0; ccnxTlvDictionaryEntryTypeStrings[i].string != NULL; i++) {
+ if (ccnxTlvDictionaryEntryTypeStrings[i].type == entryType) {
+ return ccnxTlvDictionaryEntryTypeStrings[i].string;
+ }
+ }
+ return ccnxTlvDictionaryTypeUnknown;
+}
+
+static const char *
+_ccnxTlvDictionaryTypeToString(_CCNxTlvDictionaryType dictionaryType)
+{
+ for (int i = 0; ccnxTlvDictionaryTypeStrings[i].string != NULL; i++) {
+ if (ccnxTlvDictionaryTypeStrings[i].type == dictionaryType) {
+ return ccnxTlvDictionaryTypeStrings[i].string;
+ }
+ }
+ return ccnxTlvDictionaryTypeUnknown;
+}
+
+
+typedef struct ccnx_tlv_dictionary_entry {
+ int entryType;
+ union u_entry {
+ PARCBuffer *buffer;
+ uint64_t integer;
+ CCNxName *name;
+ CCNxCodecNetworkBufferIoVec *vec;
+ PARCJSON *json;
+ PARCObject *object;
+ } _entry;
+} _CCNxTlvDictionaryEntry;
+
+struct ccnx_tlv_dictionary {
+#define FIXED_LIST_LENGTH 8
+ // These are linked lists where we put unknown TLV types. This one static allocation should
+ // be enough for all the current packet formats.
+ _CCNxTlvDictionaryListEntry *fixedListHeads[FIXED_LIST_LENGTH];
+
+ // if we need to allocate beyond FIXED_LIST_LENGTH, put them here
+ _CCNxTlvDictionaryListEntry **extraListHeads;
+
+ size_t fastArraySize;
+ size_t listSize;
+
+ _CCNxTlvDictionaryType dictionaryType;
+ CCNxTlvDictionary_SchemaVersion schemaVersion;
+
+ // Detects changes in the dictionary that were not caused by us
+ uint32_t generation;
+
+ struct timeval creationTime;
+
+ void (*infoFreeFunction)(void **infoPtr);
+ void *info;
+
+ // A pointer to the implementation functions for the type contained by this dictionary.
+ // It's a runtime static, and is not encoded. Thus, when a dictionary is received over
+ // the wire, it will need to be initialized based on the dictionaryType and schemaVersion.
+ CCNxMessageInterface *messageInterface;
+
+ // will be allocated as part of the ccnx_tlv_dictionary
+ _CCNxTlvDictionaryEntry directArray[CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END];
+};
+
+static _CCNxTlvDictionaryListEntry *
+_ccnxTlvDictionaryListEntry_Create(uint32_t key, const PARCBuffer *buffer)
+{
+ _CCNxTlvDictionaryListEntry *entry = parcMemory_AllocateAndClear(sizeof(_CCNxTlvDictionaryListEntry));
+ assertNotNull(entry, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(_CCNxTlvDictionaryListEntry));
+ entry->key = key;
+ entry->buffer = parcBuffer_Acquire(buffer);
+
+ return entry;
+}
+
+static void
+_ccnxTlvDictionaryListEntry_Release(_CCNxTlvDictionaryListEntry **entryPtr)
+{
+ _CCNxTlvDictionaryListEntry *entry = *entryPtr;
+ parcBuffer_Release(&entry->buffer);
+ parcMemory_Deallocate((void **) &entry);
+ *entryPtr = NULL;
+}
+
+static void
+_ccnxTlvDictionaryEntry_ListRelease(_CCNxTlvDictionaryListEntry **listHeadPtr)
+{
+ _CCNxTlvDictionaryListEntry *listHead = *listHeadPtr;
+ while (listHead) {
+ _CCNxTlvDictionaryListEntry *next = listHead->next;
+ _ccnxTlvDictionaryListEntry_Release(&listHead);
+ listHead = next;
+ }
+ *listHeadPtr = NULL;
+}
+
+static void
+_ccnxTlvDictionary_FinalRelease(CCNxTlvDictionary **dictionaryPtr)
+{
+ CCNxTlvDictionary *dictionary = *dictionaryPtr;
+
+ // release any entries stored in the fast array
+ for (int i = 0; i < dictionary->fastArraySize; i++) {
+ switch (dictionary->directArray[i].entryType) {
+ case ENTRY_BUFFER:
+ parcBuffer_Release(&dictionary->directArray[i]._entry.buffer);
+ break;
+ case ENTRY_NAME:
+ ccnxName_Release(&dictionary->directArray[i]._entry.name);
+ break;
+ case ENTRY_IOVEC:
+ ccnxCodecNetworkBufferIoVec_Release(&dictionary->directArray[i]._entry.vec);
+ break;
+ case ENTRY_JSON:
+ parcJSON_Release(&dictionary->directArray[i]._entry.json);
+ break;
+ case ENTRY_OBJECT:
+ parcObject_Release(&dictionary->directArray[i]._entry.object);
+ break;
+ default:
+ // other types are direct storage
+ break;
+ }
+ }
+
+ for (int i = 0; i < FIXED_LIST_LENGTH; i++) {
+ if (dictionary->fixedListHeads[i]) {
+ _ccnxTlvDictionaryEntry_ListRelease(&dictionary->fixedListHeads[i]);
+ }
+ }
+
+ if (dictionary->extraListHeads) {
+ for (int i = FIXED_LIST_LENGTH; i < dictionary->listSize; i++) {
+ if (dictionary->extraListHeads[i - FIXED_LIST_LENGTH]) {
+ _ccnxTlvDictionaryEntry_ListRelease(&dictionary->extraListHeads[i - FIXED_LIST_LENGTH]);
+ }
+ }
+ parcMemory_Deallocate((void **) &(dictionary->extraListHeads));
+ }
+
+ if (dictionary->infoFreeFunction) {
+ dictionary->infoFreeFunction(&dictionary->info);
+ }
+
+#if DEBUG_ALLOCS
+ printf("finalize dictionary %p (final)\n", dictionary);
+#endif
+}
+
+parcObject_ExtendPARCObject(CCNxTlvDictionary, _ccnxTlvDictionary_FinalRelease,
+ NULL, NULL, ccnxTlvDictionary_Equals, NULL, NULL, NULL);
+
+parcObject_ImplementAcquire(ccnxTlvDictionary, CCNxTlvDictionary);
+
+parcObject_ImplementRelease(ccnxTlvDictionary, CCNxTlvDictionary);
+
+static void
+_ccnxTlvDictionary_GetTimeOfDay(struct timeval *outputTime)
+{
+#ifdef DEBUG
+ // if in debug mode, time messages
+ gettimeofday(outputTime, NULL);
+#else
+ *outputTime = (struct timeval) { 0, 0 };
+#endif
+}
+
+
+CCNxTlvDictionary *
+ccnxTlvDictionary_Create(size_t bufferCount, size_t listCount)
+{
+ CCNxTlvDictionary *dictionary = (CCNxTlvDictionary *) parcObject_CreateAndClearInstance(CCNxTlvDictionary);
+
+ if (dictionary != NULL) {
+ _ccnxTlvDictionary_GetTimeOfDay(&dictionary->creationTime);
+
+ dictionary->dictionaryType = CCNxTlvDictionaryType_Unknown;
+ dictionary->fastArraySize = bufferCount;
+ dictionary->listSize = listCount;
+
+ dictionary->infoFreeFunction = NULL;
+ dictionary->info = NULL;
+
+ dictionary->extraListHeads = NULL;
+ // dictionary->directArray is allocated as part of parcObject
+ }
+
+#if DEBUG_ALLOCS
+ printf("allocate dictionary %p\n", dictionary);
+#endif
+
+ return dictionary;
+}
+
+CCNxTlvDictionary *
+ccnxTlvDictionary_ShallowCopy(const CCNxTlvDictionary *source)
+{
+ size_t bufferCount = source->fastArraySize;
+ size_t listCount = source->listSize;
+ CCNxTlvDictionary *newDictionary = ccnxTlvDictionary_Create(bufferCount, listCount);
+
+ if (newDictionary != NULL) {
+ newDictionary->dictionaryType = source->dictionaryType;
+ newDictionary->schemaVersion = source->schemaVersion;
+ newDictionary->generation = source->generation;
+ newDictionary->creationTime = source->creationTime;
+ newDictionary->messageInterface = source->messageInterface;
+ newDictionary->info = source->info;
+ newDictionary->infoFreeFunction = source->infoFreeFunction;
+
+ // Update listHeads
+ for (uint32_t key = 0; key < source->listSize; ++key) {
+ size_t listSize = ccnxTlvDictionary_ListSize(source, key);
+ for (size_t i = 0; i < listSize; ++i) {
+ PARCBuffer *buffer;
+ uint32_t bKey;
+ ccnxTlvDictionary_ListGetByPosition(source, key, i, &buffer, &bKey);
+ parcBuffer_Acquire(buffer);
+ ccnxTlvDictionary_PutListBuffer(newDictionary, key, bKey, buffer);
+ parcBuffer_Release(&buffer);
+ }
+ }
+
+ // Update directArray
+ for (uint32_t key = 0; key < source->fastArraySize; ++key) {
+ switch (source->directArray[key].entryType) {
+ case ENTRY_BUFFER:
+ ccnxTlvDictionary_PutBuffer(newDictionary, key, ccnxTlvDictionary_GetBuffer(source, key));
+ break;
+ case ENTRY_NAME:
+ ccnxTlvDictionary_PutName(newDictionary, key, ccnxTlvDictionary_GetName(source, key));
+ break;
+ case ENTRY_IOVEC:
+ ccnxTlvDictionary_PutIoVec(newDictionary, key, ccnxTlvDictionary_GetIoVec(source, key));
+ break;
+ case ENTRY_JSON:
+ ccnxTlvDictionary_PutJson(newDictionary, key, ccnxTlvDictionary_GetJson(source, key));
+ break;
+ case ENTRY_INTEGER:
+ ccnxTlvDictionary_PutInteger(newDictionary, key, ccnxTlvDictionary_GetInteger(source, key));
+ break;
+ case ENTRY_OBJECT:
+ ccnxTlvDictionary_PutObject(newDictionary, key, ccnxTlvDictionary_GetObject(source, key));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return newDictionary;
+}
+
+bool
+ccnxTlvDictionary_PutBuffer(CCNxTlvDictionary *dictionary, uint32_t key, const PARCBuffer *buffer)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertNotNull(buffer, "Parameter buffer must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_UNSET) {
+ dictionary->directArray[key].entryType = ENTRY_BUFFER;
+ dictionary->directArray[key]._entry.buffer = parcBuffer_Acquire(buffer);
+ return true;
+ }
+ return false;
+}
+
+bool
+ccnxTlvDictionary_PutObject(CCNxTlvDictionary *dictionary, uint32_t key, const PARCObject *object)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertNotNull(object, "Parameter object must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key %ud must be less than %zu", key, dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_UNSET) {
+ dictionary->directArray[key].entryType = ENTRY_OBJECT;
+ dictionary->directArray[key]._entry.object = parcObject_Acquire(object);
+ return true;
+ }
+ return false;
+}
+
+bool
+ccnxTlvDictionary_PutName(CCNxTlvDictionary *dictionary, uint32_t key, const CCNxName *name)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertNotNull(name, "Parameter buffer must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_UNSET) {
+ dictionary->directArray[key].entryType = ENTRY_NAME;
+ dictionary->directArray[key]._entry.name = ccnxName_Acquire(name);
+ return true;
+ }
+ return false;
+}
+
+bool
+ccnxTlvDictionary_PutInteger(CCNxTlvDictionary *dictionary, uint32_t key, const uint64_t value)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_UNSET || dictionary->directArray[key].entryType == ENTRY_INTEGER) {
+ dictionary->directArray[key].entryType = ENTRY_INTEGER;
+ dictionary->directArray[key]._entry.integer = value;
+ return true;
+ }
+ return false;
+}
+
+bool
+ccnxTlvDictionary_PutIoVec(CCNxTlvDictionary *dictionary, uint32_t key, const CCNxCodecNetworkBufferIoVec *vec)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertNotNull(vec, "Parameter buffer must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_UNSET) {
+ dictionary->directArray[key].entryType = ENTRY_IOVEC;
+ dictionary->directArray[key]._entry.vec = ccnxCodecNetworkBufferIoVec_Acquire((CCNxCodecNetworkBufferIoVec *) vec);
+ return true;
+ }
+ return false;
+}
+
+bool
+ccnxTlvDictionary_PutJson(CCNxTlvDictionary *dictionary, uint32_t key, const PARCJSON *json)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertNotNull(json, "Parameter json must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_UNSET) {
+ dictionary->directArray[key].entryType = ENTRY_JSON;
+ dictionary->directArray[key]._entry.json = parcJSON_Acquire(json);
+ return true;
+ }
+ return false;
+}
+
+CCNxCodecNetworkBufferIoVec *
+ccnxTlvDictionary_GetIoVec(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_IOVEC) {
+ return dictionary->directArray[key]._entry.vec;
+ }
+ return NULL;
+}
+
+// If you need to change the list head, use this
+static _CCNxTlvDictionaryListEntry **
+_getListHeadReference(CCNxTlvDictionary *dictionary, uint32_t listKey)
+{
+ if (listKey < FIXED_LIST_LENGTH) {
+ return &dictionary->fixedListHeads[listKey];
+ } else {
+ if (dictionary->extraListHeads == NULL) {
+ dictionary->extraListHeads = parcMemory_AllocateAndClear(sizeof(_CCNxTlvDictionaryListEntry *) * (dictionary->listSize - FIXED_LIST_LENGTH));
+ }
+
+ return &dictionary->extraListHeads[listKey - FIXED_LIST_LENGTH];
+ }
+}
+
+// If not going to modify the list, use this
+static _CCNxTlvDictionaryListEntry *
+_getListHead(const CCNxTlvDictionary *dictionary, uint32_t listKey)
+{
+ _CCNxTlvDictionaryListEntry **head = _getListHeadReference((CCNxTlvDictionary *) dictionary, listKey);
+ return *head;
+}
+
+bool
+ccnxTlvDictionary_PutListBuffer(CCNxTlvDictionary *dictionary, uint32_t listKey, uint32_t key, const PARCBuffer *buffer)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertNotNull(buffer, "Parameter buffer must be non-null");
+ assertTrue(listKey < dictionary->listSize, "Parameter key must be less than %zu", dictionary->listSize);
+
+ _CCNxTlvDictionaryListEntry *entry = _ccnxTlvDictionaryListEntry_Create(key, buffer);
+
+ _CCNxTlvDictionaryListEntry **head = _getListHeadReference(dictionary, listKey);
+ if (*head) {
+ // insert new value at list head
+ entry->next = *head;
+ *head = entry;
+ } else {
+ // new value is the list head
+ *head = entry;
+ }
+ return true;
+}
+
+bool
+ccnxTlvDictionary_IsValueBuffer(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+ return (dictionary->directArray[key].entryType == ENTRY_BUFFER);
+}
+
+bool
+ccnxTlvDictionary_IsValueObject(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+ return (dictionary->directArray[key].entryType == ENTRY_OBJECT);
+}
+
+bool
+ccnxTlvDictionary_IsValueInteger(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+ return (dictionary->directArray[key].entryType == ENTRY_INTEGER);
+}
+
+bool
+ccnxTlvDictionary_IsValueName(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+ return (dictionary->directArray[key].entryType == ENTRY_NAME);
+}
+
+bool
+ccnxTlvDictionary_IsValueIoVec(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+ return (dictionary->directArray[key].entryType == ENTRY_IOVEC);
+}
+
+bool
+ccnxTlvDictionary_IsValueJson(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+ return (dictionary->directArray[key].entryType == ENTRY_JSON);
+}
+
+PARCBuffer *
+ccnxTlvDictionary_GetBuffer(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ // For now return NULL for backward compatability with prior code, case 1011
+ if (dictionary->directArray[key].entryType == ENTRY_BUFFER) {
+ return dictionary->directArray[key]._entry.buffer;
+ }
+ return NULL;
+}
+
+CCNxName *
+ccnxTlvDictionary_GetName(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_NAME) {
+ return dictionary->directArray[key]._entry.name;
+ }
+ return NULL;
+}
+
+uint64_t
+ccnxTlvDictionary_GetInteger(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ trapIllegalValueIf(dictionary->directArray[key].entryType != ENTRY_INTEGER,
+ "Key %u is of type %d",
+ key, dictionary->directArray[key].entryType)
+ {
+ ccnxTlvDictionary_Display(dictionary, 3);
+ }
+
+ return dictionary->directArray[key]._entry.integer;
+}
+
+
+PARCJSON *
+ccnxTlvDictionary_GetJson(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_JSON) {
+ return dictionary->directArray[key]._entry.json;
+ }
+ return NULL;
+}
+
+PARCObject *
+ccnxTlvDictionary_GetObject(const CCNxTlvDictionary *dictionary, uint32_t key)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(key < dictionary->fastArraySize, "Parameter key must be less than %zu", dictionary->fastArraySize);
+
+ if (dictionary->directArray[key].entryType == ENTRY_OBJECT) {
+ return dictionary->directArray[key]._entry.object;
+ }
+
+ return NULL;
+}
+
+bool
+ccnxTlvDictionary_ListGetByPosition(const CCNxTlvDictionary *dictionary, uint32_t listKey, size_t listPosition, PARCBuffer **bufferPtr, uint32_t *keyPtr)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertNotNull(bufferPtr, "Parameter bufferPtr must be non-null");
+ assertNotNull(keyPtr, "Parameter keyPtr must be non-null");
+ assertTrue(listKey < dictionary->listSize, "Parameter key must be less than %zu", dictionary->listSize);
+
+ _CCNxTlvDictionaryListEntry *entry = _getListHead(dictionary, listKey);
+ while (entry) {
+ if (listPosition == 0) {
+ *bufferPtr = entry->buffer;
+ *keyPtr = entry->key;
+ return true;
+ }
+ entry = entry->next;
+ --listPosition;
+ }
+
+ return false;
+}
+
+
+PARCBuffer *
+ccnxTlvDictionary_ListGetByType(const CCNxTlvDictionary *dictionary, uint32_t listKey, uint32_t type)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(listKey < dictionary->listSize, "Parameter key must be less than %zu", dictionary->listSize);
+
+ PARCBuffer *buffer = NULL;
+ _CCNxTlvDictionaryListEntry *entry = _getListHead(dictionary, listKey);
+ while (entry) {
+ if (entry->key == type) {
+ buffer = entry->buffer;
+ break;
+ }
+ entry = entry->next;
+ }
+
+ return buffer;
+}
+
+
+size_t
+ccnxTlvDictionary_ListSize(const CCNxTlvDictionary *dictionary, uint32_t listKey)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertTrue(listKey < dictionary->listSize, "Parameter key must be less than %zu", dictionary->listSize);
+
+ size_t size = 0;
+ _CCNxTlvDictionaryListEntry *entry = _getListHead(dictionary, listKey);
+ while (entry) {
+ size++;
+ entry = entry->next;
+ }
+
+ return size;
+}
+
+void
+ccnxTlvDictionary_SetMessageType_Interest(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion)
+{
+ dictionary->dictionaryType = CCNxTlvDictionaryType_Interest;
+ dictionary->schemaVersion = schemaVersion;
+}
+
+void
+ccnxTlvDictionary_SetMessageType_ContentObject(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion)
+{
+ dictionary->dictionaryType = CCNxTlvDictionaryType_ContentObject;
+ dictionary->schemaVersion = schemaVersion;
+}
+
+void
+ccnxTlvDictionary_SetMessageType_Control(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion)
+{
+ dictionary->dictionaryType = CCNxTlvDictionaryType_Control;
+ dictionary->schemaVersion = schemaVersion;
+}
+
+void
+ccnxTlvDictionary_SetMessageType_InterestReturn(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion)
+{
+ dictionary->dictionaryType = CCNxTlvDictionaryType_InterestReturn;
+ dictionary->schemaVersion = schemaVersion;
+}
+
+void
+ccnxTlvDictionary_SetMessageType_Manifest(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion)
+{
+ dictionary->dictionaryType = CCNxTlvDictionaryType_Manifest;
+ dictionary->schemaVersion = schemaVersion;
+}
+
+bool
+ccnxTlvDictionary_IsInterest(const CCNxTlvDictionary *dictionary)
+{
+ return (dictionary->dictionaryType == CCNxTlvDictionaryType_Interest);
+}
+
+bool
+ccnxTlvDictionary_IsInterestReturn(const CCNxTlvDictionary *dictionary)
+{
+ return (dictionary->dictionaryType == CCNxTlvDictionaryType_InterestReturn);
+}
+
+bool
+ccnxTlvDictionary_IsContentObject(const CCNxTlvDictionary *dictionary)
+{
+ return (dictionary->dictionaryType == CCNxTlvDictionaryType_ContentObject);
+}
+
+bool
+ccnxTlvDictionary_IsControl(const CCNxTlvDictionary *dictionary)
+{
+ return (dictionary->dictionaryType == CCNxTlvDictionaryType_Control);
+}
+
+bool
+ccnxTlvDictionary_IsManifest(const CCNxTlvDictionary *dictionary)
+{
+ return (dictionary->dictionaryType == CCNxTlvDictionaryType_Manifest);
+}
+
+CCNxTlvDictionary_SchemaVersion
+ccnxTlvDictionary_GetSchemaVersion(const CCNxTlvDictionary *dictionary)
+{
+ return dictionary->schemaVersion;
+}
+
+void
+ccnxTlvDictionary_SetMessageInterface(CCNxTlvDictionary *dictionary, const CCNxMessageInterface *implementation)
+{
+ dictionary->messageInterface = (CCNxMessageInterface *) implementation;
+}
+
+CCNxMessageInterface *
+ccnxTlvDictionary_GetMessageInterface(const CCNxTlvDictionary *dictionary)
+{
+ return dictionary->messageInterface;
+}
+
+struct timeval
+ccnxTlvDictionary_GetLifetime(const CCNxTlvDictionary *dictionary)
+{
+ struct timeval now;
+ _ccnxTlvDictionary_GetTimeOfDay(&now);
+ timersub(&now, &dictionary->creationTime, &now);
+ return now;
+}
+
+static void
+_ccnxTlvDictionary_DisplayBuffer(const _CCNxTlvDictionaryEntry *entry, int index)
+{
+ printf(" Entry %3d type %8s pointer %p\n", index, _ccnxTlvDictionaryEntryTypeToString(entry->entryType), (void *) entry->_entry.buffer);
+ parcBuffer_Display(entry->_entry.buffer, 6);
+}
+
+static void
+_ccnxTlvDictionary_DisplayInteger(const _CCNxTlvDictionaryEntry *entry, int index)
+{
+ printf(" Entry %3d type %8s value 0x%" PRIX64 " (%" PRIu64 ")\n", index, _ccnxTlvDictionaryEntryTypeToString(entry->entryType), entry->_entry.integer, entry->_entry.integer);
+}
+
+static void
+_ccnxTlvDictionary_DisplayIoVec(const _CCNxTlvDictionaryEntry *entry, int index)
+{
+ printf(" Entry %3d type %8s pointer %p\n", index, _ccnxTlvDictionaryEntryTypeToString(entry->entryType), (void *) entry->_entry.vec);
+ ccnxCodecNetworkBufferIoVec_Display(entry->_entry.vec, 6);
+}
+
+static void
+_ccnxTlvDictionary_DisplayJson(const _CCNxTlvDictionaryEntry *entry, int index)
+{
+ printf(" Entry %3d type %8s pointer %p\n", index, _ccnxTlvDictionaryEntryTypeToString(entry->entryType), (void *) entry->_entry.json);
+ char *string = parcJSON_ToString(entry->_entry.json);
+ printf("%s\n", string);
+ parcMemory_Deallocate((void **) &string);
+}
+
+static void
+_ccnxTlvDictionary_DisplayName(const _CCNxTlvDictionaryEntry *entry, int index)
+{
+ printf(" Entry %3d type %8s pointer %p\n", index, _ccnxTlvDictionaryEntryTypeToString(entry->entryType), (void *) entry->_entry.name);
+ ccnxName_Display(entry->_entry.name, 6);
+}
+
+static void
+_ccnxTlvDictionary_DisplayUnknown(const _CCNxTlvDictionaryEntry *entry, int index)
+{
+ printf(" Entry %3d type %8s pointer %p\n", index, _ccnxTlvDictionaryEntryTypeToString(entry->entryType), (void *) entry->_entry.buffer);
+}
+
+static void
+_ccnxTlvDictionary_DisplayListEntry(const _CCNxTlvDictionaryListEntry *entry, int listIndex, int position)
+{
+ printf(" List %3d Position %3d key 0x%04X pointer %p\n", listIndex, position, entry->key, (void *) entry->buffer);
+ parcBuffer_Display(entry->buffer, 6);
+}
+
+void
+ccnxTlvDictionary_Display(const CCNxTlvDictionary *dictionary, int indent)
+{
+ parcDisplayIndented_PrintLine(indent, "CCNxTlvDictionary@%p fastArraySize %zu listSize %zu dictionaryType %s schemaVersion %d refcount %" PRIu64 "\n",
+ (void *) dictionary,
+ dictionary->fastArraySize,
+ dictionary->listSize,
+ _ccnxTlvDictionaryTypeToString(dictionary->dictionaryType),
+ dictionary->schemaVersion,
+ parcObject_GetReferenceCount((PARCObject *) dictionary));
+
+ parcDisplayIndented_PrintLine(indent, " createTime %0.6f generation %u Info %p InfoFreeFunc %p\n",
+ (dictionary->creationTime.tv_sec + dictionary->creationTime.tv_usec * 1E-6),
+ dictionary->generation,
+ (void *) dictionary->info,
+ dictionary->infoFreeFunction);
+
+ for (int i = 0; i < dictionary->fastArraySize; i++) {
+ if (dictionary->directArray[i].entryType != ENTRY_UNSET) {
+ switch (dictionary->directArray[i].entryType) {
+ case ENTRY_BUFFER:
+ _ccnxTlvDictionary_DisplayBuffer(&dictionary->directArray[i], i);
+ break;
+
+ case ENTRY_INTEGER:
+ _ccnxTlvDictionary_DisplayInteger(&dictionary->directArray[i], i);
+ break;
+
+ case ENTRY_IOVEC:
+ _ccnxTlvDictionary_DisplayIoVec(&dictionary->directArray[i], i);
+ break;
+
+ case ENTRY_JSON:
+ _ccnxTlvDictionary_DisplayJson(&dictionary->directArray[i], i);
+ break;
+
+ case ENTRY_NAME:
+ _ccnxTlvDictionary_DisplayName(&dictionary->directArray[i], i);
+ break;
+
+ default:
+ _ccnxTlvDictionary_DisplayUnknown(&dictionary->directArray[i], i);
+ }
+ }
+ }
+
+ for (int i = 0; i < dictionary->listSize; i++) {
+ _CCNxTlvDictionaryListEntry *entry = _getListHead(dictionary, i);
+ if (entry) {
+ int position = 0;
+ printf(" Displaying custom entry list index %3d head %p\n", i, (void *) entry);
+ while (entry) {
+ _ccnxTlvDictionary_DisplayListEntry(entry, i, position);
+ entry = entry->next;
+ }
+ }
+ }
+}
+
+static bool
+_ccnxTlvDictionaryEntry_Equals(const _CCNxTlvDictionaryEntry *a, const _CCNxTlvDictionaryEntry *b)
+{
+ if (a == NULL && b == NULL) {
+ return true;
+ }
+
+ if (a == NULL || b == NULL) {
+ return false;
+ }
+
+ bool equals = false;
+ if (a->entryType == b->entryType) {
+ switch (a->entryType) {
+ case ENTRY_UNSET:
+ equals = true;
+ break;
+
+ case ENTRY_BUFFER:
+ equals = parcBuffer_Equals(a->_entry.buffer, b->_entry.buffer);
+ break;
+
+ case ENTRY_OBJECT:
+ equals = parcObject_Equals(a->_entry.object, b->_entry.object);
+ break;
+
+ case ENTRY_INTEGER:
+ equals = (a->_entry.integer == b->_entry.integer);
+ break;
+
+ case ENTRY_IOVEC:
+ equals = ccnxCodecNetworkBufferIoVec_Equals(a->_entry.vec, b->_entry.vec);
+ break;
+
+ case ENTRY_JSON:
+ equals = parcJSON_Equals(a->_entry.json, b->_entry.json);
+ break;
+
+ case ENTRY_NAME:
+ equals = ccnxName_Equals(a->_entry.name, b->_entry.name);
+ break;
+
+ default:
+ trapIllegalValue(a->entryType, "Cannot compare due to unknown entry type: %d", a->entryType);
+ }
+ }
+ return equals;
+}
+
+static bool
+_ccnxTlvDictionaryListEntry_Equals(const _CCNxTlvDictionaryListEntry *a, const _CCNxTlvDictionaryListEntry *b)
+{
+ if (a == NULL && b == NULL) {
+ return true;
+ }
+
+ if (a == NULL || b == NULL) {
+ return false;
+ }
+
+ if (a->key == b->key) {
+ if (parcBuffer_Equals(a->buffer, b->buffer)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+_ccnxTlvDictionary_ListEquals(const _CCNxTlvDictionaryListEntry *listHeadA, const _CCNxTlvDictionaryListEntry *listHeadB)
+{
+ if (listHeadA == NULL && listHeadB == NULL) {
+ return true;
+ }
+
+ if (listHeadA == NULL || listHeadB == NULL) {
+ return false;
+ }
+
+ // walk both linked lists in parallel
+ while (listHeadA && listHeadB) {
+ if (!_ccnxTlvDictionaryListEntry_Equals(listHeadA, listHeadB)) {
+ return false;
+ }
+
+ listHeadA = listHeadA->next;
+ listHeadB = listHeadB->next;
+ }
+
+ // they must both be NULL otherwise the lists did not end at same place
+ if (listHeadA == NULL && listHeadB == NULL) {
+ return true;
+ }
+ return false;
+}
+
+/*
+ * precondition: we know they are not null and they have the same fastarray size
+ */
+static bool
+_ccnxTlvDictionary_FastArrayEquals(const CCNxTlvDictionary *a, const CCNxTlvDictionary *b)
+{
+ bool equals = true;
+ for (int i = 0; i < a->fastArraySize && equals; i++) {
+ equals = _ccnxTlvDictionaryEntry_Equals(&a->directArray[i], &b->directArray[i]);
+ }
+ return equals;
+}
+
+/*
+ * preconditiona: we know they are not null and they have the same list size
+ */
+static bool
+_ccnxTlvDictionary_ListsEquals(const CCNxTlvDictionary *a, const CCNxTlvDictionary *b)
+{
+ bool equals = true;
+ for (int i = 0; i < a->listSize && equals; i++) {
+ _CCNxTlvDictionaryListEntry *entry_a = _getListHead(a, i);
+ _CCNxTlvDictionaryListEntry *entry_b = _getListHead(b, i);
+ equals = _ccnxTlvDictionary_ListEquals(entry_a, entry_b);
+ }
+ return equals;
+}
+
+bool
+ccnxTlvDictionary_Equals(const CCNxTlvDictionary *a, const CCNxTlvDictionary *b)
+{
+ if (a == NULL && b == NULL) {
+ return true;
+ }
+
+ if (a == NULL || b == NULL) {
+ return false;
+ }
+
+ // They are both non-null
+ bool equals = false;
+ if (a->fastArraySize == b->fastArraySize) {
+ if (a->listSize == b->listSize) {
+ if (a->dictionaryType == b->dictionaryType) {
+ if (a->schemaVersion == b->schemaVersion) {
+ if (_ccnxTlvDictionary_FastArrayEquals(a, b)) {
+ if (_ccnxTlvDictionary_ListsEquals(a, b)) {
+ equals = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return equals;
+}
diff --git a/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h b/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h
new file mode 100755
index 00000000..bae0ec8b
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_TlvDictionary.h
@@ -0,0 +1,1127 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ccnx_TlvDictionary.h
+ * @brief Stores pointers to PARCBuffers indexed by keys
+ *
+ * A message dictionary stores each field of a message in an array entry. The user of the dictionary needs to
+ * have a schema so it knows which array entry is which field.
+ *
+ * A message dictionary carries two distinguished fields that are not part of the array. The MessageType is
+ * Interest, ContentObject, or Control. The SchemaVersion is 0 or 1. These fields are independent of
+ * anything that is in the dictionary.
+ *
+ * The message dictionary creates two arrays. The first array is an array of PARCBuffer. The second array
+ * is a list of (type, PARCBuffer). This structure is designed such that well-known TLV keys
+ * are stored in the first array under well-known indicies.
+ *
+ * unknown TLV keys are stored in the second array, where each list corresponds to a TLV container.
+ * For example, an unknown TLV type found under the Content Object Metadata container would
+ * go in a list corresponding to the Metadata container and they be added to the list with the
+ * pair (type, PARCBuffer), where 'type' is the unknown TLV type.
+ *
+ */
+
+#ifndef libccnx_ccnx_TlvDictionary_h
+#define libccnx_ccnx_TlvDictionary_h
+
+#include <stdbool.h>
+#include <sys/time.h>
+#include <parc/algol/parc_Buffer.h>
+#include <parc/algol/parc_JSON.h>
+
+#include <ccnx/common/internal/ccnx_MessageInterface.h>
+
+#include <ccnx/common/ccnx_Name.h>
+#include <ccnx/common/codec/ccnxCodec_NetworkBuffer.h>
+
+
+struct ccnx_tlv_dictionary;
+typedef struct ccnx_tlv_dictionary CCNxTlvDictionary;
+
+typedef enum {
+ CCNxTlvDictionary_SchemaVersion_V0 = 0,
+ CCNxTlvDictionary_SchemaVersion_V1 = 1,
+} CCNxTlvDictionary_SchemaVersion;
+
+
+/**
+ * Creates a new TLV dictionary with the given size
+ *
+ * There will be 'bufferCount' array elements of type Buffer and
+ * 'listCount' elements of type List. Each array is indexed from 0.
+ *
+ * @param [in] bufferCount The number of Buffer elements to allocate within the dictionary.
+ * @param [in] listCount The number of List elements to allocate within the dictionary.
+ *
+ * @return NULL A new CCNxTlvDictionary object could not be allocated.
+ * @return CCNxTlvDictionary A new CCNxTlvDictionary instance with bufferCount Buffer and listCount List elements.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_PutBuffer(dict, 3, nameBuffer);
+ * rtatlvDictionary_PutListBuffer(dict, 2, unknownType, unknownBuffer);
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary *ccnxTlvDictionary_Create(size_t bufferCount, size_t listCount);
+
+/**
+ * Acquire a handle to the CCNxTlvDictionary instance.
+ *
+ * Note that new instance is not created,
+ * only that the given instance's reference count is incremented.
+ * Discard the reference by invoking `ccnxTlvDictionary_Release()`.
+ *
+ * @param [in] dictionary A pointer to the original instance.
+ * @return The value of the input parameter @p instance.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Acquire(instance);
+ *
+ * ccnxTlvDictionary_Release(&dict);
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary *ccnxTlvDictionary_Acquire(const CCNxTlvDictionary *dictionary);
+
+/**
+ * Release a previously acquired reference to the specified instance,
+ * decrementing the reference count for the instance.
+ *
+ * The pointer to the instance is set to NULL as a side-effect of this function.
+ *
+ * If the invocation causes the last reference to the instance to be released,
+ * the instance is deallocated and the instance's implementation will perform
+ * additional cleanup and release other privately held references.
+ *
+ * @param [in] dictionaryPtr A pointer to a pointer to the instance to release.
+ *
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Acquire(instance);
+ *
+ * ccnxTlvDictionary_Release(&dict);
+ * }
+ * @endcode
+ */
+void ccnxTlvDictionary_Release(CCNxTlvDictionary **dictionaryPtr);
+
+/**
+ * Adds a buffer to a dictionary entry
+ *
+ * Stores a reference count to the buffer
+ *
+ * @param [in] dictionary An CCNxTlvDictionary instance to which the Buffer entry will be added.
+ * @param [in] key The integer key that is to be associated with the new Buffer entry.
+ * @param [in] buffer The Buffer entry value to be inserted into the dictionary.
+ *
+ * @return true Key was not previously set
+ * @return false Key already has a buffer assigned to it
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCBuffer *buffer = parcBuffer_Allocate(1);
+ * ccnxTlvDictionary_PutBuffer(dict, 1, buffer);
+ * // use the dictionary as needed
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_PutBuffer(CCNxTlvDictionary *dictionary, uint32_t key, const PARCBuffer *buffer);
+
+/**
+ * Determine if the value associated with the specified key is a Buffer.
+ *
+ * The key must be within the interval [0, bufferCount] for the dictionary.
+ *
+ * @param [in] dictionary The dictionary instance which will be examined.
+ * @param [in] key The key to use when indexing the dictionary.
+ *
+ * @return true The value associated with the key is of type Buffer.
+ * @return false The value associated with the key is -not- of type Buffer.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCBuffer *buffer = parcBuffer_Allocate(1);
+ * ccnxTlvDictionary_PutBuffer(dict, 1, buffer);
+ * bool truthy = ccnxTlvDictionary_IsValueBuffer(dict, 1);
+ * // truthy will be true
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsValueBuffer(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+// caw TODO
+bool ccnxTlvDictionary_IsValueObject(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Retrieves an entry from the dictionary from the specified key.
+ *
+ * @param [in] dictionary The dictionary instance which will be examined.
+ * @param [in] key The key to use when indexing the dictionary.
+ *
+ * @return NULL if key not found
+ * @return non-null The desired key
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCBuffer *buffer = parcBuffer_Allocate(1);
+ * ccnxTlvDictionary_PutBuffer(dict, 1, buffer);
+ * PARCBuffer *copy = ccnxTlvDictionary_GetBuffer(dict, 1);
+ * // copy will be equal to the buffer instance
+ * }
+ * @endcode
+ */
+PARCBuffer *ccnxTlvDictionary_GetBuffer(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Put a new integer value in the dictionary, overwriting the old value if the key is
+ * already present.
+ *
+ * You can put an integer value many times, its OK to overwrite.
+ * They key must be UNSET or INTEGER, you cannot overwrite a different type
+ * The integer will be encoded as per the schema, it will not necessarily be an 8-byte field.
+ *
+ * @param [in] dictionary The dictionary instance to be modified
+ * @param [in] key The key used when indexing the dictionary
+ * @param [in] value The new value to insert into the dictionary assoicated with the above key
+ *
+ * @return true If the put/update was successful.
+ * @return false Otherwise (e.g., not UNSET/INTEGER type)
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * bool success = ccnxTlvDictionary_PutInteger(dict, 2, 1337);
+ * // success will be true since key 2 was UNSET
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_PutInteger(CCNxTlvDictionary *dictionary, uint32_t key, const uint64_t value);
+
+/**
+ * Determine if the value associated with the specified key is an Integer.
+ *
+ * The key must be within the interval [0, bufferCount] for the dictionary.
+ *
+ * @param [in] dictionary The dictionary instance which will be examined.
+ * @param [in] key The key to use when indexing the dictionary.
+ *
+ * @return true The value associated with the key is of type INTEGER.
+ * @return false The value associated with the key is -not- of type INTEGER.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_PutInteger(dict, 2, 1337);
+ * bool truthy = ccnxTlvDictionary_IsValueInteger(dict, 2);
+ * // truthy will be true
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsValueInteger(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Returns an integer value stored in a key
+ *
+ * Will trapIllegalValue if the given key is not of type Integer. You should use
+ * ccnxTlvDictionary_IsValueInteger before calling. An unset key is not of type Integer.
+ *
+ * @param [in] dictionary The dictionary to check
+ * @param [in] key The key to retrieve
+ *
+ * @return number The value stored under the key
+ *
+ * Example:
+ * @code
+ * static uint32_t
+ * _fetchUint32(const CCNxTlvDictionary *interestDictionary, uint32_t key, uint32_t defaultValue)
+ * {
+ * if (ccnxTlvDictionary_IsValueInteger(interestDictionary, key)) {
+ * return (uint32_t) ccnxTlvDictionary_GetInteger(interestDictionary, key);
+ * }
+ * return defaultValue;
+ * }
+ * @endcode
+ */
+uint64_t ccnxTlvDictionary_GetInteger(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Put a new CCNxName into the `CCNxTlvDictionary` instance.
+ *
+ * You can only set a Name field once. The key must be UNSET.
+ *
+ * @param [in] dictionary The dictionary instance to be modified
+ * @param [in] key The key used when indexing the dictionary
+ * @param [in] name The new CCNxName value to insert into the dictionary assoicated with the above key
+ *
+ * @return true If the put/update was successful.
+ * @return false Otherwise (e.g., not UNSET type)
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar");
+ * bool success = ccnxTlvDictionary_PutName(dict, 2, name);
+ * // success will be true since key 2 was UNSET
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_PutName(CCNxTlvDictionary *dictionary, uint32_t key, const CCNxName *name);
+
+/**
+ * Determine if the value associated with the specified key is a CCNxName.
+ *
+ * The key must be within the interval [0, bufferCount] for the dictionary.
+ *
+ * @param [in] dictionary The dictionary instance which will be examined.
+ * @param [in] key The key to use when indexing the dictionary.
+ *
+ * @return true The value associated with the key is of type NAME.
+ * @return false The value associated with the key is -not- of type NAME.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar");
+ * ccnxTlvDictionary_PutName(dict, 2, name);
+ * bool truthy = ccnxTlvDictionary_IsValueName(dict, 2);
+ * // truthy will be true since a name was inserted with key=2
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsValueName(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Retrieve the CCNxName instance associated with the specified key.
+ *
+ * The key must be within the interval [0, bufferCount] for the dictionary.
+ * The entry is expected to be of type NAME, and will return NULL if not.
+ *
+ * @param [in] dictionary The dictionary instance which will be queried.
+ * @param [in] key The key to use when indexing the dictionary.
+ *
+ * @return NULL The entry associated with the key is not of type NAME.
+ * @return CCNxName A CCNxName instance associated with the specified key.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar");
+ * ccnxTlvDictionary_PutName(dict, 2, name);
+ * CCNxName *copy = ccnxTlvDictionary_GetName(dict, 2);
+ * // do something with copy
+ * }
+ * @endcode
+ */
+CCNxName *ccnxTlvDictionary_GetName(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Insert a `CCNxCodecNetworkBufferIoVec` instance into the dictionary.
+ *
+ * Stores a scatter/gather network buffer. Could be either the wire format we recieve
+ * or the wire format we're about to send. The resulting entry type will be IOVEC.
+ *
+ * @param [in] dictionary The dictionary instance to be modified
+ * @param [in] key The key used when indexing the dictionary
+ * @param [in] vec The new CCNxCodecNetworkBufferIoVec value to insert into the dictionary assoicated with the above key
+ *
+ * @return true If the put/update was successful.
+ * @return false Otherwise (e.g., not UNSET type)
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * CCNxCodecNetworkBuffer *buffer = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL);
+ * CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(buffer);
+ * bool success = ccnxTlvDictionary_PutName(dict, 2, iovec);
+ * // success will be true since key 2 was UNSET
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_PutIoVec(CCNxTlvDictionary *dictionary, uint32_t key, const CCNxCodecNetworkBufferIoVec *vec);
+
+/**
+ * Determine if the value associated with the specified key is a CCNxCodecNetworkBufferIoVec.
+ *
+ * @param [in] dictionary The dictionary instance to be examined
+ * @param [in] key The key used when indexing the dictionary
+ *
+ * @return true The TLV dictionary has the given key and it is of type IOVEC
+ * @return false Otherwise
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * CCNxCodecNetworkBuffer *buffer = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL);
+ * CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(buffer);
+ * ccnxTlvDictionary_PutName(dict, 2, iovec);
+ * bool truthy = ccnxTlvDictionary_IsValueIoVec(dict, 2);
+ * // truthy will be true since key 2 was IOVEC and previously inserted
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsValueIoVec(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Retrieve the CCNxCodecNetworkBufferIoVec instance associated with the specified key.
+ *
+ * The key must be within the interval [0, bufferCount] for the dictionary.
+ * The entry is expected to be of type IOVEC, and will return NULL if not.
+ *
+ * @param [in] dictionary The dictionary instance which will be queried.
+ * @param [in] key The key to use when indexing the dictionary.
+ *
+ * @return NULL The entry associated with the key is not of type IOVEC.
+ * @return CCNxCodecNetworkBufferIoVec A CCNxCodecNetworkBufferIoVec instance associated with the specified key.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * CCNxCodecNetworkBuffer *buffer = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL);
+ * CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(buffer);
+ * ccnxTlvDictionary_PutName(dict, 2, iovec);
+ * CCNxCodecNetworkBufferIoVec *copy = ccnxTlvDictionary_GetIoVec(dict, 2);
+ * // do something with copy
+ * }
+ * @endcode
+ */
+CCNxCodecNetworkBufferIoVec *ccnxTlvDictionary_GetIoVec(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Insert a new List item into the dictionary.
+ *
+ * The key must be within the interval [0, bufferCount] for the dictionary.
+ * You can only set a Buffer field once. The key must be UNSET.
+ *
+ * @param [in] dictionary The dictionary instance to be modified
+ * @param [in] listKey The list key used when indexing the dictionary lists
+ * @param [in] key The key type of the element being inserted into the list
+ * @param [in] buffer The new PARCBuffer value to insert into the dictionary list indexed by the listKey
+ *
+ * @return true If the put/update was successful.
+ * @return false Otherwise (e.g., not UNSET type)
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCBuffer *buffer = parcBuffer_Allocate(1);
+ * bool success = ccnxTlvDictionary_PutListBuffer(dict, 1, 1, buffer);
+ * // success will be true since list key 1 was UNSET, and the new item will have key type 1
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_PutListBuffer(CCNxTlvDictionary *dictionary, uint32_t listKey, uint32_t key, const PARCBuffer *buffer);
+
+/**
+ * Insert a new `PARCJSON` instance into the dictionary.
+ *
+ * The caller may destroy its reference to JSON since the type is deep-copied internally.
+ * The key must be within the dictionary, and the entry must be UNSET.
+ *
+ * @param [in] dictionary The dictionary instance to be modified
+ * @param [in] key The key used when indexing the dictionary
+ * @param [in] json The new PARCJSON value to insert into the dictionary associated with the above key
+ *
+ * @return true If the put/update was successful.
+ * @return false Otherwise (e.g., not UNSET type)
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCJSON *json = ccnxJson_CreateNumber(1);
+ * bool success = ccnxTlvDictionary_PutJson(dict, 1, json);
+ * // success will be true since the key was UNSET
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_PutJson(CCNxTlvDictionary *dictionary, uint32_t key, const PARCJSON *json);
+
+/**
+ * Determine if the value associated with the specified key is a `PARCJSON` instance.
+ *
+ * @param [in] dictionary The dictionary instance to be examined
+ * @param [in] key The key used when indexing the dictionary
+ *
+ * @return true The TLV dictionary has the given key and it is of type JSON
+ * @return false Otherwise
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCJSON *json = ccnxJson_CreateNumber(1);
+ * ccnxTlvDictionary_PutJson(dict, 1, json);
+ * bool truthy = ccnxTlvDictionary_IsValueJson(dict, 1);
+ * // truthy will be true since the JSON object was previously inserted
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsValueJson(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Retrieve the `PARCJSON` instance associated with the specified key.
+ *
+ * The key must be within the interval [0, bufferCount] for the dictionary.
+ * The entry is expected to be of type JSON, and will return NULL if not.
+ *
+ * @param [in] dictionary The dictionary instance which will be queried.
+ * @param [in] key The key to use when indexing the dictionary.
+ *
+ * @return NULL The entry associated with the key is not of type JSON.
+ * @return PARCJSON A PARCJSON instance associated with the specified key.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCJSON *json = ccnxJson_CreateNumber(1);
+ * ccnxTlvDictionary_PutJson(dict, 1, json);
+ * PARCJSON *copy = ccnxTlvDictionary_GetJson(dict, 1);
+ * // do something with copy
+ * }
+ * @endcode
+ */
+PARCJSON *ccnxTlvDictionary_GetJson(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Insert a new `PARCJSON` instance into the dictionary.
+ *
+ * The caller may destroy its reference to PARCObject since the type is deep-copied internally.
+ * The key must be within the dictionary, and the entry must be UNSET.
+ *
+ * @param [in] dictionary The dictionary instance to be modified
+ * @param [in] key The key used when indexing the dictionary
+ * @param [in] json The new PARCObject value to insert into the dictionary associated with the above key
+ *
+ * @return true If the put/update was successful.
+ * @return false Otherwise (e.g., not UNSET type)
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCObject *object = ccnxName_CreateFromCString("ccnx/test");
+ * bool success = ccnxTlvDictionary_PutObject(dict, 1, object);
+ * // success will be true since the key was UNSET
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_PutObject(CCNxTlvDictionary *dictionary, uint32_t key, const PARCObject *json);
+
+/**
+ * Determine if the value associated with the specified key is a `PARCObject` instance.
+ *
+ * @param [in] dictionary The dictionary instance to be examined
+ * @param [in] key The key used when indexing the dictionary
+ *
+ * @return true The TLV dictionary has the given key and it is of type PARCObject
+ * @return false Otherwise
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCObject *object = ccnxName_CreateFromCString("ccnx/test");
+ * ccnxTlvDictionary_PutObject(dict, 1, object);
+ * bool truthy = ccnxTlvDictionary_IsValueObject(dict, 1);
+ * // truthy will be true since the PARCObject was previously inserted
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsValueObject(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Retrieve the `PARCObject` instance associated with the specified key.
+ *
+ * The key must be within the interval [0, bufferCount] for the dictionary.
+ * The entry is expected to be of type PARCObject, and will return NULL if not.
+ *
+ * @param [in] dictionary The dictionary instance which will be queried.
+ * @param [in] key The key to use when indexing the dictionary.
+ *
+ * @return NULL The entry associated with the key is not of type PARCObject.
+ * @return PARCObject A PARCObject instance associated with the specified key.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCObject *object = ccnxName_CreateFromCString("ccnx/test");
+ * ccnxTlvDictionary_PutObject(dict, 1, object);
+ * PARCObject *copy = ccnxTlvDictionary_GetObject(dict, 1);
+ * // do something with copy
+ * }
+ * @endcode
+ */
+PARCObject *ccnxTlvDictionary_GetObject(const CCNxTlvDictionary *dictionary, uint32_t key);
+
+/**
+ * Fetches a buffer from the ordinal position 'listItem' from the list key 'key'
+ *
+ * The entry 'key' must be type list.
+ *
+ * @param [in] dictionary The dictionary instance being examined
+ * @param [in] listKey The key used to identify the list to be searched
+ * @param [in] listPosition The index within the target list of the dictionary
+ * @param [out] bufferPtr If position is found, the buffer at that position
+ * @param [out] keyPtr If position is found, the key of the buffer
+ *
+ * @return true position found
+ * @return false position not found
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCBuffer *buffer = parcBuffer_Allocate(1);
+ * ccnxTlvDictionary_PutListBuffer(dict, 1, 1, buffer);
+ * PARCBuffer *copy = NULL;
+ * uint32_t key = 0;
+ * ccnxTlvDictionary_ListGetByPosition(dict, 1, 0, &copy, &key);
+ * // use the copy and key as necessary
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_ListGetByPosition(const CCNxTlvDictionary *dictionary, uint32_t listKey, size_t listPosition, PARCBuffer **bufferPtr, uint32_t *keyPtr);
+
+/**
+ * Returns the first buffer in the list identified by 'listkey' with the buffer type 'type'
+ *
+ * @param [in] dictionary The dictionary instance being examined
+ * @param [in] listKey The key used to index into the dictionary lists
+ * @param [in] type The type of element used to search within the dictionary list
+ *
+ * @return PARCBuffer* Pointer to the first PARCBuffer instance whose type matches the type argument in the target list
+ * @return NULL If no element in the target list has the specified type.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCBuffer *buffer = parcBuffer_Allocate(1);
+ * ccnxTlvDictionary_PutListBuffer(dict, 1, 1, buffer);
+ * PARCBuffer *copy = ccnxTlvDictionary_ListGetByType(dict, 1, 1);
+ * // copy and buffer will have equal PARCBuffer values
+ * }
+ * @endcode
+ */
+PARCBuffer *ccnxTlvDictionary_ListGetByType(const CCNxTlvDictionary *dictionary, uint32_t listKey, uint32_t type);
+
+/**
+ * Retrieve the number of elements in the list identified by 'key'
+ *
+ * The dictionary entry 'key' must be of type list.
+ *
+ * @param [in] dictionary The dictionary instance to be examined
+ * @param [in] listKey The key used to index into the list whose size will be checked
+ *
+ * @return The size of the list associated with the given list key
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * PARCBuffer *buffer = parcBuffer_Allocate(1);
+ * ccnxTlvDictionary_PutListBuffer(dict, 1, 1, buffer);
+ * size_t listSize = ccnxTlvDictionary_ListSize(dictionary, 1);
+ * // listSize will be 1
+ * }
+ * @endcode
+ */
+size_t ccnxTlvDictionary_ListSize(const CCNxTlvDictionary *dictionary, uint32_t listKey);
+
+/**
+ * Set the type of message which this dictionary stores/represents to be an Interest.
+ *
+ * @param [in] dictionary The dictionary instance whose type is to be modified
+ * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_Interest(dict, CCNxTlvDictionary_SchemaVersion_V0);
+ * // use the dictionary
+ * }
+ * @endcode
+ */
+void ccnxTlvDictionary_SetMessageType_Interest(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion);
+
+/**
+ * Set the type of message which this dictionary stores/represents to be a ContentObject.
+ *
+ * @param [in] dictionary The dictionary instance whose type is to be modified
+ * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_ContentObject(dict, CCNxTlvDictionary_SchemaVersion_V1);
+ * // use the dictionary
+ * }
+ * @endcode
+ */
+void ccnxTlvDictionary_SetMessageType_ContentObject(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion);
+
+/**
+ * Set the type of message which this dictionary stores/represents to be a Control (message).
+ *
+ * @param [in] dictionary The dictionary instance whose type is to be modified
+ * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_Control(dict, CCNxTlvDictionary_SchemaVersion_V1);
+ * // use the dictionary
+ * }
+ * @endcode
+ */
+void ccnxTlvDictionary_SetMessageType_Control(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion);
+
+/**
+ * Set the type of message which this dictionary stores/represents to be a Manifest (message).
+ *
+ * @param [in] dictionary The dictionary instance whose type is to be modified.
+ * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_Manifest(dict, CCNxTlvDictionary_SchemaVersion_V1);
+ * // use the dictionary
+ * }
+ * @endcode
+ */
+void ccnxTlvDictionary_SetMessageType_Manifest(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion);
+
+/**
+ * Set the type of message which this dictionary stores/represents to be an InterestReturn.
+ *
+ * @param [in] dictionary The dictionary instance whose type is to be modified
+ * @param [in] schemaVersion The schema version which is used by the dictionary for message encoding.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_InterestReturn(dict, CCNxTlvDictionary_SchemaVersion_V0);
+ * // use the dictionary
+ * }
+ * @endcode
+ */
+void ccnxTlvDictionary_SetMessageType_InterestReturn(CCNxTlvDictionary *dictionary, CCNxTlvDictionary_SchemaVersion schemaVersion);
+
+
+/**
+ * Retrieve the schema version `CCNxTlvDictionary_SchemaVersion` used to encode the contents of the dictionary.
+ *
+ * Currently, only two schema versions are supported: CCNxTlvDictionary_SchemaVersion_V0 and CCNxTlvDictionary_SchemaVersion_V1
+ *
+ * @param [in] dictionary The dictionary instance being examined
+ *
+ * @return The `CCNxTlvDictionary_SchemaVersion` version used for encoding.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_Interest(dict, CCNxTlvDictionary_SchemaVersion_V0);
+ * CCNxTlvDictionary_SchemaVersion ver = ccnxTlvDictionary_GetSchemaVersion(dict);
+ * // ver will be equal to CCNxTlvDictionary_SchemaVersion_V0
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary_SchemaVersion ccnxTlvDictionary_GetSchemaVersion(const CCNxTlvDictionary *dictionary);
+
+/**
+ * Determine if the specified dictionary represents an Interest message.
+ *
+ * @param [in] dictionary The dictionary instance being examined.
+ *
+ * @return true The dictionary represents an Interest message.
+ * @return false Otherwise
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_Interest(dict, CCNxTlvDictionary_SchemaVersion_V0);
+ * bool isInterest = ccnxTlvDictionary_IsInterest(dict);
+ * // isInterest will be true
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsInterest(const CCNxTlvDictionary *dictionary);
+
+/**
+ * Determine if the specified dictionary represents an InterestReturn message.
+ *
+ * @param [in] dictionary The dictionary instance being examined.
+ *
+ * @return true The dictionary represents an InterestReturn message.
+ * @return false Otherwise
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_InterestReturn(dict, CCNxTlvDictionary_SchemaVersion_V1);
+ * bool isInterestReturn = ccnxTlvDictionary_IsInterestReturn(dict);
+ * // isInterest will be true
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsInterestReturn(const CCNxTlvDictionary *dictionary);
+
+/**
+ * Determine if the specified dictionary represents a ContentObject message.
+ *
+ * @param [in] dictionary The dictionary instance being examined.
+ *
+ * @return true The dictionary represents a ContentObject message.
+ * @return false Otherwise
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_ContentObject(dict, CCNxTlvDictionary_SchemaVersion_V0);
+ * bool isContentObject = ccnxTlvDictionary_IsContentObject(dict);
+ * // isContentObject will be true
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsContentObject(const CCNxTlvDictionary *dictionary);
+
+/**
+ * Determine if the specified dictionary represents a Control message.
+ *
+ * @param [in] dictionary The dictionary instance being examined.
+ *
+ * @return true The dictionary represents a Control message.
+ * @return false Otherwise
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_Control(dict, CCNxTlvDictionary_SchemaVersion_V0);
+ * bool isControl = ccnxTlvDictionary_IsControl(dict);
+ * // isControl will be true
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsControl(const CCNxTlvDictionary *dictionary);
+
+/**
+ * Determine if the specified dictionary represents a Manifest message.
+ *
+ * @param [in] dictionary The dictionary instance being examined.
+ *
+ * @return true The dictionary represents a Manifest message.
+ * @return false Otherwise
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ *
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageType_Manifest(dict, CCNxTlvDictionary_SchemaVersion_V1);
+ * bool isManifest = ccnxTlvDictionary_IsManifest(dict);
+ * // isManifest will be true
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_IsManifest(const CCNxTlvDictionary *dictionary);
+
+/**
+ * If in DEBUG mode, returns how long the message has been in the system
+ *
+ * If not in DEBUG mode, will always be {.tv_sec = 0, .tv_usec = 0}. The time is based
+ * on gettimeofday().
+ *
+ * Measured since the time when the dictionary was created
+ *
+ * @param [in] dictionary The dictionary instance whose lifetime is being queried
+ *
+ * @return struct timeval The lifetime of the dictionary message.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * // do some things ...
+ * struct timeval = ccnxTlvDictionary_GetLifetime(dict);
+ * // use the time as needed
+ * }
+ * @endcode
+ */
+struct timeval ccnxTlvDictionary_GetLifetime(const CCNxTlvDictionary *dictionary);
+
+/**
+ * Display the dictionary and its contents
+ *
+ * The contents of the dictionary are printed to stdout. This is often useful
+ * for verbose debugging purposes.
+ *
+ * @param [in] indent The number of tabs to indent all lines printed on stdout
+ * @param [in] dictionary The dictionary instance whose contents will be printed to stdout
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_Display(dict, 0);
+ * }
+ * @endcode
+ */
+void ccnxTlvDictionary_Display(const CCNxTlvDictionary *dictionary, int indent);
+
+/**
+ * Determine if two CCNxTlvDictionary instances are equal.
+ *
+ * Two CCNxTlvDictionary instances are equal if, and only if, they contain the same number
+ * of keys, the keys are equal, and each key points to the same value.
+ *
+ * The following equivalence relations on non-null `CCNxTlvDictionary` instances are maintained:
+ *
+ * * It is reflexive: for any non-null reference value x, `ccnxTlvDictionary_Equals(x, x)`
+ * must return true.
+ *
+ * * It is symmetric: for any non-null reference values x and y,
+ * `ccnxTlvDictionary_Equals(x, y)` must return true if and only if
+ * `ccnxTlvDictionary_Equals(y, x)` returns true.
+ *
+ * * It is transitive: for any non-null reference values x, y, and z, if
+ * `ccnxTlvDictionary_Equals(x, y)` returns true and
+ * `ccnxTlvDictionary_Equals(y, z)` returns true,
+ * then `ccnxTlvDictionary_Equals(x, z)` must return true.
+ *
+ * * It is consistent: for any non-null reference values x and y, multiple
+ * invocations of `ccnxTlvDictionary_Equals(x, y)` consistently return true or
+ * consistently return false.
+ *
+ * * For any non-null reference value x, `ccnxTlvDictionary_Equals(x, NULL)` must
+ * return false.
+ *
+ * @param a A pointer to a `CCNxTlvDictionary` instance.
+ * @param b A pointer to a `CCNxTlvDictionary` instance.
+ *
+ * NULL == NULL, non-NULL != NULL, otherwise the dictionaries need to be the same
+ * type, schema, and all fields must compare for equality.
+ *
+ * Equals does not include the CreationTime (lifetime) or the SetInfo() value.
+ *
+ * @return true Dictionaries are equal
+ * @return false Dictionaries differ in some way
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ * CCNxTlvDictionary *dict1 = ccnxTlvDictionary_Create(5, 3);
+ * CCNxTlvDictionary *dict2 = ccnxTlvDictionary_Create(5, 3);
+ * if (ccnxTlvDictionary_Equals(dict1, dict2)) {
+ * // true
+ * } else {
+ * // false
+ * }
+ * }
+ * @endcode
+ */
+bool ccnxTlvDictionary_Equals(const CCNxTlvDictionary *a, const CCNxTlvDictionary *b);
+
+/**
+ * Allocates a new instance of the specified CCNxTlvDictionary that is
+ * a "Shallow" copy of the original. The new instance contains the
+ * same contents as the original CCNxTlvDictionary but an Acquire()
+ * operation is used where possible to form a new link to the original
+ * contained content (a Copy() operation is used otherwise). Note that
+ * this means that modifying the content of the copy will, in most
+ * cases, modify the content of the original. In any case, the
+ * contents are protected from premature deallocation.
+ *
+ * @param [in] source The dictionary to copy
+ *
+ * @return CCNxTlvDictionary A pointer to a copy of the source dictionary
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ * CCNxTlvDictionary *source = ccnxTlvDictionary_Create(5, 3);
+ * PARCBuffer *buffer = parcBuffer_Allocate(1);
+ * ccnxTlvDictionary_PutListBuffer(source, 1, 1, buffer);
+ * ...
+ * CCNxTlvDictionary *copy = ccnxTlvDictionary_ShallowCopy(source);
+ * PARCBuffer *buffcopy;
+ * uint32_t key = 0;
+ * ccnxTlvDictionary_ListGetByPosition(copy, 1, 0, &buffcopy, &key);
+ * ...
+ * assertTrue(ccnxTlvDictionary_Equals(source, copy), "Error: not a copy");
+ * assertTrue(buffcopy == buffer, "Error: not a shallow copy");
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary *ccnxTlvDictionary_ShallowCopy(const CCNxTlvDictionary *source);
+
+/**
+ * Set the pointer to the implementation used to create the message type represented by this
+ * CCNxTlvDictionary. For example, if the CCNxTlvDictionary represents a V1 ContentObject,
+ * the implementation pointer should be set to &CCNxContentObjectFacadeV1_Implementation.
+ * The type can be inferred from the dictionary's schemaVersion and messageType.
+ *
+ * Consumers of this CCNxTlvDictionary should use the implementation pointer to access
+ * fields in the dictionary. Examples of implementations would be those that define
+ * {@link CCNxContentObjectInterface} or {@link CCNxInterestInterface}, such as
+ * {@link CCNxContentObjectFacadeV1_Implementation} or {CCNxInterestFacadeV1_Implementation}.
+ *
+ * @param [in] dictionary The dictionary instance on which to set the implementation pointer.
+ * @param [in] implementation The address of the implementation to be used to access this dictionary.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageInterface(&CCNxContentObjectFacadeV1_Implementation);
+ * }
+ * @endcode
+ * @see `ccnxTlvDictionary_GetMessageTypeInterface`
+ */
+void ccnxTlvDictionary_SetMessageInterface(CCNxTlvDictionary *dictionary, const CCNxMessageInterface *implementation);
+
+/**
+ * Return the address of the implementation used to access fields in the the message represented by this
+ * CCNxTlvDictionary instance. The implementation pointer would typically be
+ * {@link CCNxContentObjectFacadeV1_Implementation} or {@link CCNxContentObjectFacadeV1_Implementation}.
+ * If it is not set, it can be inferred from the messageType and the schemaVersion.
+ *
+ * @param [in] dictionary The dictionary instance from which to retrieve the implementation pointer.
+ *
+ * Example:
+ * @code
+ * {
+ * ...
+ * CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(5, 3);
+ * ccnxTlvDictionary_SetMessageTypeInterface(&CCNxContentObjectFacadeV1_Implementation);
+ * CCNxContentObjectInterface *impl = ccnxTlvDictionary_GetMessageTypeInterface(dict);
+ * }
+ * @endcode
+ * @see `ccnxTlvDictionary_SetMessageTypeInterface`
+ * @see `ccnxContentObjectInterface_GetInterface`
+ * @see `ccnxInterestInterface_GetInterface`
+ */
+CCNxMessageInterface *ccnxTlvDictionary_GetMessageInterface(const CCNxTlvDictionary *dictionary);
+#endif // libccnx_ccnx_TlvDictionary_h
diff --git a/libccnx-common/ccnx/common/internal/ccnx_TlvError.c b/libccnx-common/ccnx/common/internal/ccnx_TlvError.c
new file mode 100755
index 00000000..0f07ab9e
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_TlvError.c
@@ -0,0 +1,167 @@
+/*
+ * 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/internal/ccnx_TlvError.h>
+
+struct error_messages {
+ CCNxTlvErrorCodes code;
+ const char *message;
+} TlvErrorMessages[] = {
+ { .code = TLV_ERR_NO_ERROR, .message = "No error" },
+ { .code = TLV_ERR_VERSION, .message = "Unsupported version" },
+ { .code = TLV_ERR_PACKETTYPE, .message = "Unsupported packet type" },
+ { .code = TLV_ERR_BEYOND_PACKET_END, .message = "Field goes beyond end of packet" },
+ { .code = TLV_ERR_TOO_LONG, .message = "Length too long for parent container" },
+ { .code = TLV_ERR_NOT_FIXED_SIZE, .message = "Fixed size Type wrong Length" },
+ { .code = TLV_ERR_DUPLICATE_FIELD, .message = "Duplicate field" },
+ { .code = TLV_ERR_EMPTY_SPACE, .message = "The sum of child TLVs did not add up to parent container length" },
+
+ // missing mandatory field errors
+ { .code = TLV_MISSING_MANDATORY, .message = "Missing mandatory field" },
+
+ { .code = TLV_ERR_DECODE, .message = "Decoding error" },
+
+ // end of list sentinel, the NULL determines the end of list
+ { .code = UINT16_MAX, .message = NULL }
+};
+
+
+const char *
+ccnxTlvErrors_ErrorMessage(CCNxTlvErrorCodes code)
+{
+ for (int i = 0; TlvErrorMessages[i].message != NULL; i++) {
+ if (TlvErrorMessages[i].code == code) {
+ return TlvErrorMessages[i].message;
+ }
+ }
+ return "No error message found";
+}
+
+// ==========================================================================
+
+struct ccnx_tlv_error {
+ CCNxTlvErrorCodes code;
+ const char *functionName;
+ int line;
+ size_t byteOffset;
+ unsigned refcount;
+ char *toString;
+};
+
+CCNxTlvError *
+ccnxTlvError_Create(CCNxTlvErrorCodes code, const char *func, int line, size_t byteOffset)
+{
+ CCNxTlvError *error = parcMemory_AllocateAndClear(sizeof(CCNxTlvError));
+ assertNotNull(error, "parcMemory_AllocateAndClear(%u) returned NULL", sizeof(CCNxTlvError));
+ error->code = code;
+ error->functionName = func;
+ error->line = line;
+ error->byteOffset = byteOffset;
+ error->toString = NULL; // computed on the fly
+ error->refcount = 1;
+ return error;
+}
+
+CCNxTlvError *
+ccnxTlvError_Acquire(CCNxTlvError *error)
+{
+ assertNotNull(error, "Parameter error must be non-null");
+ assertTrue(error->refcount > 0, "Parameter has 0 refcount, not valid");
+
+ error->refcount++;
+ return error;
+}
+
+void
+ccnxTlvError_Release(CCNxTlvError **errorPtr)
+{
+ assertNotNull(errorPtr, "Parameter must be non-null double pointer");
+ assertNotNull(*errorPtr, "Parameter must derefernece to non-null pointer");
+ CCNxTlvError *error = *errorPtr;
+
+ assertTrue(error->refcount > 0, "Parameter has 0 refcount, not valid");
+ error->refcount--;
+ if (error->refcount == 0) {
+ if (error->toString) {
+ // this is asprintf generated
+ free(error->toString);
+ }
+ parcMemory_Deallocate((void **) &error);
+ }
+ *errorPtr = NULL;
+}
+
+size_t
+ccnxTlvError_GetByteOffset(const CCNxTlvError *error)
+{
+ assertNotNull(error, "Parameter must be non-null");
+ return error->byteOffset;
+}
+
+
+CCNxTlvErrorCodes
+ccnxTlvError_GetErrorCode(const CCNxTlvError *error)
+{
+ assertNotNull(error, "Parameter must be non-null");
+ return error->code;
+}
+
+const char *
+ccnxTlvError_GetFunction(const CCNxTlvError *error)
+{
+ assertNotNull(error, "Parameter must be non-null");
+ return error->functionName;
+}
+
+int
+ccnxTlvError_GetLine(const CCNxTlvError *error)
+{
+ assertNotNull(error, "Parameter must be non-null");
+ return error->line;
+}
+
+const char *
+ccnxTlvError_GetErrorMessage(const CCNxTlvError *error)
+{
+ assertNotNull(error, "Parameter must be non-null");
+ return ccnxTlvErrors_ErrorMessage(error->code);
+}
+
+const char *
+ccnxTlvError_ToString(CCNxTlvError *error)
+{
+ assertNotNull(error, "Parameter must be non-null");
+ if (error->toString) {
+ return error->toString;
+ }
+
+ asprintf(&error->toString, "TLV error: %s:%d offset %zu: %s",
+ error->functionName,
+ error->line,
+ error->byteOffset,
+ ccnxTlvError_GetErrorMessage(error));
+
+ return error->toString;
+}
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ValidationFacadeV1.c b/libccnx-common/ccnx/common/internal/ccnx_ValidationFacadeV1.c
new file mode 100755
index 00000000..d9f86895
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ValidationFacadeV1.c
@@ -0,0 +1,203 @@
+/*
+ * 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 <config.h>
+#include <stdio.h>
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/internal/ccnx_ValidationFacadeV1.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+static void
+_assertInvariants(const CCNxTlvDictionary *message)
+{
+ assertNotNull(message, "Parameter message must be non-null");
+}
+
+PARCBuffer *
+ccnxValidationFacadeV1_GetKeyId(const CCNxTlvDictionary *message)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_GetBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID);
+}
+
+CCNxLink *
+ccnxValidationFacadeV1_GetKeyName(const CCNxTlvDictionary *message)
+{
+ _assertInvariants(message);
+ CCNxLink *link = NULL;
+ CCNxName *name = ccnxTlvDictionary_GetName(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME);
+ if (name) {
+ PARCBuffer *keyid = ccnxTlvDictionary_GetBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_KEYID);
+ PARCBuffer *hash = ccnxTlvDictionary_GetBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_OBJHASH);
+
+ link = ccnxLink_Create(name, keyid, hash);
+ }
+ return link;
+}
+
+PARCBuffer *
+ccnxValidationFacadeV1_GetPublicKey(const CCNxTlvDictionary *message)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_GetBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY);
+}
+
+PARCBuffer *
+ccnxValidationFacadeV1_GetCertificate(const CCNxTlvDictionary *message)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_GetBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CERT);
+}
+
+PARCBuffer *
+ccnxValidationFacadeV1_GetPayload(const CCNxTlvDictionary *message)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_GetBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+}
+
+bool
+ccnxValidationFacadeV1_HasCryptoSuite(const CCNxTlvDictionary *message)
+{
+ bool hasCryptoSuite = false;
+ _assertInvariants(message);
+ if (ccnxTlvDictionary_IsValueInteger(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE)) {
+ hasCryptoSuite = true;
+ }
+ return hasCryptoSuite;
+}
+
+PARCCryptoSuite
+ccnxValidationFacadeV1_GetCryptoSuite(const CCNxTlvDictionary *message)
+{
+ if (ccnxValidationFacadeV1_HasCryptoSuite(message)) {
+ return (PARCCryptoSuite) ccnxTlvDictionary_GetInteger(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE);
+ }
+
+ trapUnexpectedState("Dictionary does not have a CryptoSuite set");
+}
+
+bool
+ccnxValidationFacadeV1_HasSigningTime(const CCNxTlvDictionary *message)
+{
+ bool hasSigningTime = false;
+ _assertInvariants(message);
+ if (ccnxTlvDictionary_IsValueInteger(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME)) {
+ hasSigningTime = true;
+ }
+ return hasSigningTime;
+}
+
+uint64_t
+ccnxValidationFacadeV1_GetSigningTime(const CCNxTlvDictionary *message)
+{
+ if (ccnxValidationFacadeV1_HasSigningTime(message)) {
+ return ccnxTlvDictionary_GetInteger(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME);
+ }
+
+ trapUnexpectedState("Dictionary does not have a CryptoSuite set");
+}
+
+// ===========================================================
+// Setters
+
+bool
+ccnxValidationFacadeV1_SetKeyId(CCNxTlvDictionary *message, const PARCBuffer *keyid)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID, keyid);
+}
+
+bool
+ccnxValidationFacadeV1_SetKeyName(CCNxTlvDictionary *message, const CCNxLink *keyNameLink)
+{
+ _assertInvariants(message);
+ const CCNxName *name = ccnxLink_GetName(keyNameLink);
+ bool success = ccnxTlvDictionary_PutName(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME, name);
+ if (success) {
+ PARCBuffer *keyid = ccnxLink_GetKeyID(keyNameLink);
+ if (keyid) {
+ success = ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_KEYID, keyid);
+ }
+
+ if (success) {
+ PARCBuffer *hash = ccnxLink_GetContentObjectHash(keyNameLink);
+ success = ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_OBJHASH, hash);
+ }
+ }
+ return success;
+}
+
+bool
+ccnxValidationFacadeV1_SetKeyLocator(CCNxTlvDictionary *message, CCNxKeyLocator *keyLocator)
+{
+ bool success = true;
+ if (keyLocator) {
+ if (ccnxKeyLocator_IsKey(keyLocator)) {
+ PARCKey *key = ccnxKeyLocator_GetKey(keyLocator);
+ PARCBuffer *keybuffer = parcKey_GetKey(key);
+ success &= ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY, keybuffer);
+ } else if (ccnxKeyLocator_IsKeyLink(keyLocator)) {
+ CCNxLink *link = ccnxKeyLocator_GetKeyLink(keyLocator);
+ const CCNxName *name = ccnxLink_GetName(link);
+
+ // Support KeyId and COH as part of the keyname, case 1012
+ success &= ccnxTlvDictionary_PutName(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME, name);
+ } else {
+ trapUnrecoverableState("KeyLocator is not a known type");
+ }
+ }
+ return success;
+}
+
+bool
+ccnxValidationFacadeV1_SetPublicKey(CCNxTlvDictionary *message, const PARCBuffer *derEncodedKey)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY, derEncodedKey);
+}
+
+bool
+ccnxValidationFacadeV1_SetCertificate(CCNxTlvDictionary *message, const PARCBuffer *derEncodedCertificate)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CERT, derEncodedCertificate);
+}
+
+bool
+ccnxValidationFacadeV1_SetCryptoSuite(CCNxTlvDictionary *message, PARCCryptoSuite suite)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_PutInteger(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE, suite);
+}
+
+bool
+ccnxValidationFacadeV1_SetSigningTime(CCNxTlvDictionary *message, uint64_t signingTime)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_PutInteger(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME, signingTime);
+}
+
+bool
+ccnxValidationFacadeV1_SetPayload(CCNxTlvDictionary *message, const PARCBuffer *validationPayload)
+{
+ _assertInvariants(message);
+ return ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD, validationPayload);
+}
+
diff --git a/libccnx-common/ccnx/common/internal/ccnx_ValidationFacadeV1.h b/libccnx-common/ccnx/common/internal/ccnx_ValidationFacadeV1.h
new file mode 100644
index 00000000..524efe7e
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_ValidationFacadeV1.h
@@ -0,0 +1,474 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file ccnx_ValidationFacadeV1.h
+ * @brief Generic functions to fetch/set the KeyId, PublicKey, Certificate, or validation payload
+ *
+ * The Validation Facade may be used directly on CCNxInterest or CCNxContentObject structures, for example:
+ *
+ * @code
+ * {
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/foo");
+ * CCNxContentObject *object = ccnxContentObject_CreateWithNameAndPayload(name, NULL);
+ * ccnxName_Release(&name);
+ * // generate the KeyId
+ * ccnxValidationFacadeV1_SetKeyId(object, keyId);
+ * }
+ * @endcode
+ *
+ */
+
+#ifndef libccnx_ccnx_ValidationFacadeV1_h
+#define libccnx_ccnx_ValidationFacadeV1_h
+
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/ccnx_KeyLocator.h>
+
+#include <ccnx/common/ccnx_Link.h>
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <parc/security/parc_CryptoSuite.h>
+
+
+// ===========================================================
+// Validation Algorithm
+
+#include <ccnx/common/validation/ccnxValidation_CRC32C.h>
+#include <ccnx/common/validation/ccnxValidation_EcSecp256K1.h>
+#include <ccnx/common/validation/ccnxValidation_HmacSha256.h>
+#include <ccnx/common/validation/ccnxValidation_RsaSha256.h>
+
+// ===========================================================
+// Getters
+
+/**
+ * If the Validation Algorithm has a KeyId field, return it if it exists
+ *
+ * Not all validation algorithms have a KeyId field. Only true signature algoritms, such as
+ * RSA or ECC should always have one. HMAC or other MACs often use the KeyId to identify a
+ * key agreed to via a key exchange protocol, so the meaning is only applicable to those parties.
+ * Integrity checks, such as CRC-32C, do not have a KeyId.
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @retval non-null The KeyId field of the Validation Algorithm
+ * @retval null KeyId is missing
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * PARCBuffer *keyid = ccnxValidationFacadeV1_GetKeyId(dictionary);
+ * }
+ * @endcode
+ */
+PARCBuffer *ccnxValidationFacadeV1_GetKeyId(const CCNxTlvDictionary *message);
+
+/**
+ * If the Validation Algorithm has a KeyName, return the embedded Link
+ *
+ * The returned CCNxLink is allocated on function call, so caller must
+ * release it when done.
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @retval non-null The KeyName link of the Validation Algorithm (must be released)
+ * @retval null KeyName is missing
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * CCNxLink *link = ccnxValidationFacadeV1_GetKeyName(dictionary);
+ * }
+ * @endcode
+ */
+CCNxLink *ccnxValidationFacadeV1_GetKeyName(const CCNxTlvDictionary *mesage);
+
+/**
+ * If the Validation Algorithm has a Public Key embedded, return it
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @retval non-null The KeyId field of the Validation Algorithm
+ * @retval null KeyId is missing
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * PARCBuffer *publicKeyDEREncoding = ccnxValidationFacadeV1_GetPublicKey(dictionary);
+ * }
+ * @endcode
+ */
+PARCBuffer *ccnxValidationFacadeV1_GetPublicKey(const CCNxTlvDictionary *message);
+
+/**
+ * If the Validation Algorithm has a Certificate embedded, return it
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @retval non-null The Certificate field of the Validation Algorithm
+ * @retval null KeyId is missing
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * PARCBuffer *x509certDEREncoding = ccnxValidationFacadeV1_GetCertificate(dictionary);
+ * }
+ * @endcode
+ */
+PARCBuffer *ccnxValidationFacadeV1_GetCertificate(const CCNxTlvDictionary *message);
+
+/**
+ * Returns the Validation Payload, if present.
+ *
+ * The validation payload is the actual bytes of the signature or authentication code or
+ * integrity check. it's format will be specific to the ValidationAlgorithm.
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @retval non-null The validation payload
+ * @retval null Validation payload does not exist
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * PARCBuffer *validationPayload = ccnxValidationFacadeV1_GetPayload(dictionary);
+ * }
+ * @endcode
+ */
+PARCBuffer *ccnxValidationFacadeV1_GetPayload(const CCNxTlvDictionary *message);
+
+/**
+ * Determines if the packet specified a supported crypto suite
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @retval true There is a valid crypto suite specified
+ * @retval false There is not a valid crypto suite specified
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * if (ccnxValidationFacadeV1_HasCryptoSuite(dictionary)) {
+ * PARCCryptoSuite suite = ccnxValidationFacadeV1_GetCryptoSuite(dictionary);
+ * // process the validation alg
+ * }
+ * }
+ * @endcode
+ */
+bool ccnxValidationFacadeV1_HasCryptoSuite(const CCNxTlvDictionary *message);
+
+/**
+ * Returns the Validation Algorithm specified in the packet
+ *
+ * If the packet specified a supported crypto suite, return the suite. If
+ * it is not a supported algorithm, function all assert an error. You must use
+ * ccnxValidationFacadeV1_HasCryptoSuite() to determine if there is a supported crypto suite.
+ *
+ * An unsupported crypto suite's entire TLV container is put in the CustomField section of
+ * the dictionary and you can retrieve it from there if you know the type or iterate the list.
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @return value The crypto suite
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * if (ccnxValidationFacadeV1_HasCryptoSuite(dictionary)) {
+ * PARCCryptoSuite suite = ccnxValidationFacadeV1_GetCryptoSuite(dictionary);
+ * // process the validation alg
+ * }
+ * }
+ * @endcode
+ */
+PARCCryptoSuite ccnxValidationFacadeV1_GetCryptoSuite(const CCNxTlvDictionary *message);
+
+/**
+ * Determines if the packet specified a signing time
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @retval true There is a signing time in the validation algorithm
+ * @retval false There is not a signing time
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * if (ccnxValidationFacadeV1_HasSigningTime(dictionary)) {
+ * uint64_t signingTime = ccnxValidationFacadeV1_GetSigningTime(dictionary);
+ * // process the signing time
+ * }
+ * }
+ * @endcode
+ */
+bool ccnxValidationFacadeV1_HasSigningTime(const CCNxTlvDictionary *message);
+
+/**
+ * Retruns the Validation Algorithm specified in the packet
+ *
+ * If the packet has a Signing Time in the Validation Algorithm, return that value. If
+ * it is not, function all assert an error. You must use
+ * ccnxValidationFacadeV1_HasSigningTime() to determine if there is a
+ * signing time.
+ *
+ * The signing time is UTC milli-seconds since the epoch.
+ *
+ * @param [in] message An allocated dictionary
+ *
+ * @return value The signing time in UTC milli-seconds since the epoch.
+ *
+ * Example:
+ * @code
+ * {
+ * PARCBuffer *wireFormat = // packet received from the network
+ * CCNxTlvDictionary *dictionary = ccnxCodecTlvPacket_Decode(wireFormat);
+ * if (ccnxValidationFacadeV1_HasSigningTime(dictionary)) {
+ * uint64_t signingTime = ccnxValidationFacadeV1_GetSigningTime(dictionary);
+ * // process the signing time
+ * }
+ * }
+ * @endcode
+ */
+uint64_t ccnxValidationFacadeV1_GetSigningTime(const CCNxTlvDictionary *message);
+
+// ===========================================================
+// Setters
+
+/**
+ * Sets the KeyId attribute of the dictionary
+ *
+ * The KeyId is a mandatory field for validation algorithms that use a key, such
+ * as HMAC or RSA or ECC.
+ *
+ * Normally, one uses a function in the ccnxValidation algoirthm to set this value
+ * such as bool ccnxValidationHmacSha256_Set(CCNxTlvDictionary *message, const PARCBuffer *keyid).
+ *
+ * @param [in] message The dictionary to set the value in
+ * @param [in] keyid The encoded value of the keyid
+ *
+ * @retval true Value set in the dictionary
+ * @retval false Error, likely the value was already set
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/foo");
+ * CCNxContentObject *object = ccnxContentObject_CreateWithNameAndPayload(name, NULL);
+ * ccnxName_Release(&name);
+ *
+ * PARCBuffer *secretKey = parcBuffer_Wrap("password", 8, 0, 8);
+ * PARCSigner *signer = ccnxValidationHmacSha256_CreateSigner(secretKey);
+ *
+ * PARCKeyId *keyid = parcSigner_CreateKeyId(signer);
+ * const PARCBuffer *keyIdBytes = parcKeyId_GetKeyId(keyid);
+ * ccnxValidationFacadeV1_SetKeyId(object, keyIdBytes);
+ * parcKeyId_Release(&keyid);
+ *
+ * // continue with signer and dictionary
+ * }
+ * @endcode
+ */
+bool ccnxValidationFacadeV1_SetKeyId(CCNxTlvDictionary *message, const PARCBuffer *keyid);
+
+
+/**
+ * Stores the KeyLocator in the standard Dictionary places for use by the standard Getters
+ *
+ * If the Validator does not need any special handing of a KeyLocator, this function
+ * will store the keylocator in the default dictionary entries for use by the standard getters.
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return <#value#> <#explanation#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxValidationFacadeV1_SetKeyLocator(CCNxTlvDictionary *message, CCNxKeyLocator *keyLocator);
+
+/**
+ * Stores the KeyName in the standard Dictionary places for use by the standard Getters
+ *
+ * Stores the fields from the Link in the dictionary.
+ *
+ * @param [in] message The message to update
+ * @param [in] keyNameLink The link to put in the dictionary
+ *
+ * @retval true Values successfully added to dictionary
+ * @retval false An error (likely a duplicate value)
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxValidationFacadeV1_SetKeyName(CCNxTlvDictionary *message, const CCNxLink *keyNameLink);
+
+/**
+ * Embeds the DER encoded public key in the Validation Algorithm
+ *
+ * If this field is not set, the public key will not be placed in the
+ * validation algorithm.
+ *
+ * @param [in] message The message to update
+ * @param [in] derEncodedKey The DER encoded public key to put in the dictionary
+ *
+ * @retval true Value successfully added to dictionary
+ * @retval false An error (likely a duplicate value)
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/foo");
+ * CCNxContentObject *object = ccnxContentObject_CreateWithNameAndPayload(name, NULL);
+ * ccnxName_Release(&name);
+ *
+ * PARCSigner *signer = parcSigner_Create(parcPublicKeySignerPkcs12Store_Open("keystore.p12", "password", PARCCryptoHashType_SHA256));
+ *
+ * PARCBuffer *publicKey = parcSigner_GetDEREncodedPublicKey(signer);
+ *
+ * ccnxValidationFacadeV1_SetPublicKey(object, publicKey);
+ *
+ * // continue with signer and dictionary
+ * } * @endcode
+ */
+bool ccnxValidationFacadeV1_SetPublicKey(CCNxTlvDictionary *message, const PARCBuffer *derEncodedKey);
+
+/**
+ * Embeds the DER encoded public key in the Validation Algorithm
+ *
+ * If this field is not set, the public key will not be placed in the
+ * validation algorithm.
+ *
+ * @param [in] message The message to update
+ * @param [in] derEncodedCertificate The DER encoded public key to put in the dictionary
+ *
+ * @retval true Value successfully added to dictionary
+ * @retval false An error (likely a duplicate value)
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxName *name = ccnxName_CreateFromCString("lci:/foo");
+ * CCNxContentObject *object = ccnxContentObject_CreateWithNameAndPayload(name, NULL);
+ * ccnxName_Release(&name);
+ *
+ * PARCSigner *signer = parcSigner_Create(parcPublicKeySignerPkcs12Store_Open("keystore.p12", "password", PARCCryptoHashType_SHA256));
+ *
+ * PARCBuffer *cert = parcSigner_GetDEREncodedCertificate(signer);
+ *
+ * ccnxValidationFacadeV1_SetPublicKey(object, cert);
+ *
+ * // continue with signer and dictionary
+ * } * @endcode
+ */
+bool ccnxValidationFacadeV1_SetCertificate(CCNxTlvDictionary *message, const PARCBuffer *derEncodedCertificate);
+
+/**
+ * Sets the crypto suite in the dictionary
+ *
+ * It is not necessary to set the crypto suite if the packet is encoded with a Signer,
+ * as the crypto suite will be derived from the signer.
+ *
+ * Normally, one uses a function in the ccnxValidation algoirthm to set this value
+ * such as bool ccnxValidationHmacSha256_Set(CCNxTlvDictionary *message, const PARCBuffer *keyid).
+ *
+ * @param [in] message The message to update
+ * @param [in] suite The cryptosuite value to set in the packet
+ *
+ * @retval true The crypto suite was set
+ * @retval false The crypto suite was not set (not supported by V1 or other error)
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxValidationFacadeV1_SetCryptoSuite(CCNxTlvDictionary *message, PARCCryptoSuite suite);
+
+/**
+ * Sets the signing time in the dictionary
+ *
+ * The signing time represents when the signature is created. It is sometimes used for
+ * replay attack prevention. It is the UTC time in milli-seconds since the epoch (i.e. a posix time).
+ *
+ * If the signing time is not specified in the dictionary, it will be automatically created
+ * based on the system clock when the signature is generated (this assumes the system clock
+ * and timezone are correctly set).
+ *
+ * @param [in] message The message to update
+ * @param [in] signingTime UTC time since the epoch in milli-seconds
+ *
+ * @retval true The value was set
+ * @retval false The value was not set (likely a duplicate value)
+ *
+ * Example:
+ * @code
+ * @endcode
+ */
+bool ccnxValidationFacadeV1_SetSigningTime(CCNxTlvDictionary *message, uint64_t signingTime);
+
+/**
+ * Saves the validation payload in the dictionary
+ *
+ * The validation payload is the output of the validation algorithm, i.e.
+ * the 32-bit CRC32C checksum or the RSA signature. Usually the Codec is setting this
+ * value after it has generated the wire format. If this value is set prior to encoding,
+ * this value will be used regardless if it is correct or not.
+ *
+ * You can only save the payload once per dictionary.
+ *
+ * @param [in] message The message to update
+ * @param [in] validationPayload The payload to put in the packet
+ *
+ * @return true Payload saved
+ * @return false Payload was already set or other error
+ *
+ * Example:
+ * @code
+ * {
+ * PARCSignature *signature = ccnxCodecTlvEncoder_ComputeSignature(encoder);
+ * PARCBuffer *sigbits = parcSignature_GetSignature(signature);
+ *
+ * // this creates its own reference to sigbits
+ * ccnxValidationFacadeV1_SetPayload(packetDictionary, sigbits);
+ *
+ * parcSignature_Release(&signature);
+ * parcBuffer_Release(&sigbits);
+ * }
+ * @endcode
+ */
+bool ccnxValidationFacadeV1_SetPayload(CCNxTlvDictionary *message, const PARCBuffer *validationPayload);
+
+#endif // libccnx_ccnx_ValidationFacadeV1_h
diff --git a/libccnx-common/ccnx/common/internal/ccnx_WireFormatFacadeV1.c b/libccnx-common/ccnx/common/internal/ccnx_WireFormatFacadeV1.c
new file mode 100644
index 00000000..daf851c7
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_WireFormatFacadeV1.c
@@ -0,0 +1,484 @@
+/*
+ * 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 <config.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <LongBow/runtime.h>
+
+#include <parc/algol/parc_FileOutputStream.h>
+
+#include <ccnx/common/internal/ccnx_WireFormatMessageInterface.h>
+#include <ccnx/common/internal/ccnx_WireFormatFacadeV1.h>
+#include <ccnx/common/ccnx_WireFormatMessage.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h>
+
+
+static CCNxTlvDictionary *
+_ccnxWireFormatFacadeV1_FromInterestPacketType(const PARCBuffer *wireFormat)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxTlvDictionary_PutBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat, wireFormat);
+ return dictionary;
+}
+
+static CCNxTlvDictionary *
+_ccnxWireFormatFacadeV1_FromInterestPacketTypeIoVec(const CCNxCodecNetworkBufferIoVec *vec)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxTlvDictionary_PutIoVec(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat, vec);
+ return dictionary;
+}
+
+static CCNxTlvDictionary *
+_ccnxWireFormatFacadeV1_FromInterestReturnPacketType(const PARCBuffer *wireFormat)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterestReturn();
+ ccnxTlvDictionary_PutBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat, wireFormat);
+ return dictionary;
+}
+
+static CCNxTlvDictionary *
+_ccnxWireFormatFacadeV1_FromContentObjectPacketType(const PARCBuffer *wireFormat)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxTlvDictionary_PutBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat, wireFormat);
+ return dictionary;
+}
+
+static CCNxTlvDictionary *
+_ccnxWireFormatFacadeV1_FromControlPacketType(const PARCBuffer *wireFormat)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateControl();
+ ccnxTlvDictionary_PutBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat, wireFormat);
+ return dictionary;
+}
+
+static CCNxCodecSchemaV1InterestHeader *
+_getWireFormatFixedHeader(CCNxTlvDictionary *dictionary)
+{
+ // Currently there is only one of either a PARCBuffer or an IoVec ...
+
+ CCNxCodecSchemaV1InterestHeader *header = NULL;
+
+ // Update attached iovec
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxWireFormatMessage_GetIoVec(dictionary);
+ if (iovec) {
+ assertTrue(ccnxCodecNetworkBufferIoVec_Length(iovec) >= sizeof(CCNxCodecSchemaV1InterestHeader),
+ "IoVector smaller than required for message header");
+ const struct iovec *iov = ccnxCodecNetworkBufferIoVec_GetArray(iovec);
+ assertTrue(iov[0].iov_len >= sizeof(CCNxCodecSchemaV1InterestHeader),
+ "Header not contained in first element of io vector");
+ header = iov[0].iov_base;
+ } else {
+ // Update attached buffer
+ PARCBuffer *wireFormatBuffer = ccnxWireFormatMessage_GetWireFormatBuffer(dictionary);
+ if (wireFormatBuffer) {
+ header = parcBuffer_Overlay(wireFormatBuffer, 0);
+ }
+ }
+
+ return header;
+}
+
+static bool
+_ccnxWireFormatFacadeV1_SetHopLimit(CCNxTlvDictionary *dictionary, uint32_t hopLimit)
+{
+ bool result = false;
+
+ CCNxCodecSchemaV1InterestHeader *header = _getWireFormatFixedHeader(dictionary);
+ if (header != NULL) {
+ header->hopLimit = hopLimit;
+ result = true;
+ }
+ return result;
+}
+
+static bool
+_ccnxWireFormatFacadeV1_ConvertInterestToInterestReturn(CCNxTlvDictionary *dictionary, uint8_t code)
+{
+ bool result = false;
+
+ CCNxCodecSchemaV1InterestHeader *header = _getWireFormatFixedHeader(dictionary);
+ if (header != NULL) {
+ header->returnCode = code;
+ header->packetType = CCNxCodecSchemaV1Types_PacketType_InterestReturn;
+ result = true;
+ }
+ return result;
+}
+
+static CCNxTlvDictionary *
+_ccnxWireFormatFacadeV1_CreateFromV1(const PARCBuffer *wireFormat)
+{
+ CCNxTlvDictionary *dictionary = NULL;
+ uint8_t packetType = parcBuffer_GetAtIndex(wireFormat, 1);
+ switch (packetType) {
+ case CCNxCodecSchemaV1Types_PacketType_ContentObject:
+ dictionary = _ccnxWireFormatFacadeV1_FromContentObjectPacketType(wireFormat);
+ break;
+ case CCNxCodecSchemaV1Types_PacketType_Control:
+ dictionary = _ccnxWireFormatFacadeV1_FromControlPacketType(wireFormat);
+ break;
+ case CCNxCodecSchemaV1Types_PacketType_Interest:
+ dictionary = _ccnxWireFormatFacadeV1_FromInterestPacketType(wireFormat);
+ break;
+ case CCNxCodecSchemaV1Types_PacketType_InterestReturn:
+ dictionary = _ccnxWireFormatFacadeV1_FromInterestReturnPacketType(wireFormat);
+ break;
+ default:
+ // will return NULL
+ break;
+ }
+ return dictionary;
+}
+
+static PARCBuffer *
+_ccnxWireFormatFacadeV1_GetWireFormatBuffer(const CCNxTlvDictionary *dictionary)
+{
+ PARCBuffer *wireFormat = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat);
+ return wireFormat;
+}
+
+static bool
+_ccnxWireFormatFacadeV1_PutWireFormatBuffer(CCNxTlvDictionary *dictionary, PARCBuffer *wireFormat)
+{
+ bool success = ccnxTlvDictionary_PutBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat, wireFormat);
+ return success;
+}
+
+static CCNxCodecNetworkBufferIoVec *
+_ccnxWireFormatFacadeV1_GetIoVec(const CCNxTlvDictionary *dictionary)
+{
+ CCNxCodecNetworkBufferIoVec *vec = ccnxTlvDictionary_GetIoVec(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat);
+ return vec;
+}
+
+static bool
+_ccnxWireFormatFacadeV1_PutIoVec(CCNxTlvDictionary *dictionary, CCNxCodecNetworkBufferIoVec *vec)
+{
+ bool success = ccnxTlvDictionary_PutIoVec(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat, vec);
+ return success;
+}
+
+static void
+_ccnxWireFormatFacadeV1_WriteToFile(const CCNxTlvDictionary *dictionary, const char *filename)
+{
+ int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ PARCFileOutputStream *fos = parcFileOutputStream_Create(fd);
+
+ PARCBuffer *wireFormat = _ccnxWireFormatFacadeV1_GetWireFormatBuffer(dictionary);
+ if (wireFormat) {
+ parcFileOutputStream_Write(fos, wireFormat);
+ parcBuffer_Rewind(wireFormat);
+ }
+
+ // this will close the file descriptor
+ parcFileOutputStream_Release(&fos);
+}
+
+static bool
+_ccnxWireFormatFacadeV1_SetProtectedRegionStart(CCNxTlvDictionary *dictionary, size_t startPosition)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ // ccnx packets work on 16-bit lengths
+ assertTrue(startPosition <= UINT16_MAX, "Start position beyond UINT16_MAX: %zu", startPosition);
+
+ bool success = ccnxTlvDictionary_PutInteger(dictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedStart,
+ startPosition);
+ return success;
+}
+
+static bool
+_ccnxWireFormatFacadeV1_SetProtectedRegionLength(CCNxTlvDictionary *dictionary, size_t length)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ // ccnx packets work on 16-bit lengths
+ assertTrue(length <= UINT16_MAX, "Length position beyond UINT16_MAX: %zu", length);
+
+ bool success = ccnxTlvDictionary_PutInteger(dictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedLength,
+ length);
+ return success;
+}
+
+static bool
+_ccnxWireFormatFacadeV1_SetContentObjectHashRegionStart(CCNxTlvDictionary *dictionary, size_t startPosition)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ // ccnx packets work on 16-bit lengths
+ assertTrue(startPosition <= UINT16_MAX, "Start position beyond UINT16_MAX: %zu", startPosition);
+
+ bool success = ccnxTlvDictionary_PutInteger(dictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ContentObjectHashRegionStart,
+ startPosition);
+ return success;
+}
+
+static bool
+_ccnxWireFormatFacadeV1_SetContentObjectHashRegionLength(CCNxTlvDictionary *dictionary, size_t length)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ // ccnx packets work on 16-bit lengths
+ assertTrue(length <= UINT16_MAX, "Length position beyond UINT16_MAX: %zu", length);
+
+ bool success = ccnxTlvDictionary_PutInteger(dictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ContentObjectHashRegionLength,
+ length);
+ return success;
+}
+
+
+/*
+ * Compute the hash over the specified region. This is a static function, so we know the caller
+ * has verified all the parameters before giving them to us.
+ * The caller must also verify that (start + length <= totalLength).
+ *
+ * As we walk through the iovecs, the variables will look like this
+ * +-----------+-----------+-----------+-----------+-----------+
+ * iov[0] iov[1] iov[2] iov[3]
+ * +-----------+-----------+-----------+-----------+-----------+
+ * ^ ^ ^ ^
+ * | | | |
+ * | start | end
+ * iovStart iovEnd
+ * |-------|---|
+ * offset
+ * remaining
+ *
+ * +-----------+-----------+-----------+-----------+-----------+
+ * iov[0] iov[1] iov[2] iov[3]
+ * +-----------+-----------+-----------+-----------+-----------+
+ * ^ ^ ^
+ * | | |
+ * start | end
+ * iovStart iovEnd
+ * |-----------|
+ * offset (0)
+ * remaining (iov_len)
+ *
+ * +-----------+-----------+-----------+-----------+-----------+
+ * iov[0] iov[1] iov[2] iov[3]
+ * +-----------+-----------+-----------+-----------+-----------+
+ * ^ ^
+ * | |
+ * start end
+ * iovStart iovEnd
+ * |------|
+ * offset (0)
+ * remaining (end-start)
+ *
+ */
+static PARCCryptoHash *
+_hashProtectedRegionIoVec(CCNxCodecNetworkBufferIoVec *vec, PARCCryptoHasher *hasher, size_t start, size_t length)
+{
+ int failure = parcCryptoHasher_Init(hasher);
+ assertFalse(failure, "Error initializing the hasher");
+
+ const struct iovec *iov = ccnxCodecNetworkBufferIoVec_GetArray(vec);
+ int iovcnt = ccnxCodecNetworkBufferIoVec_GetCount(vec);
+
+ // iovStart is the beginning position of the current iovec
+ size_t iovStart = 0;
+ size_t end = start + length;
+
+ // Once iovStart is past end, we no longer need to loop, we're done
+ for (int i = 0; i < iovcnt && iovStart < end; i++) {
+ size_t iovEnd = iovStart + iov[i].iov_len;
+ iovEnd = (iovEnd > end) ? end : iovEnd;
+
+ // is "start" contained in this iovec?
+ if (iovStart <= start && start < iovEnd) {
+ size_t offset = start - iovStart;
+ size_t remaining = iovEnd - start;
+
+ failure = parcCryptoHasher_UpdateBytes(hasher, (const void *) ((uint8_t *) iov[i].iov_base + offset), remaining);
+ assertFalse(failure, "Error updating hasher iovec %d offset %zu remaining %zu", i, offset, remaining)
+ {
+ ccnxCodecNetworkBufferIoVec_Display(vec, 3);
+ }
+
+ // keep moving start to the next iovec
+ start += remaining;
+ }
+
+ iovStart += iov[i].iov_len;
+ }
+
+ PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher);
+
+ return hash;
+}
+
+
+/*
+ * Compute the hash over the specified region. This is a static function, so we know the caller
+ * has verified all the parameters before giving them to us.
+ * The caller must also verify that (start + length <= parcBuffer_Limit).
+ *
+ * +-----------+-----------+-----------+-----------+-----------+
+ * PARCBuffer
+ * +-----------+-----------+-----------+-----------+-----------+
+ * ^ ^ ^ ^
+ * | | | |
+ * 0 start end Limit
+ */
+static PARCCryptoHash *
+_ccnxWireFormatFacadeV1_ComputeBufferHash(PARCBuffer *wireFormat, PARCCryptoHasher *hasher, size_t start, size_t length)
+{
+ int failure = parcCryptoHasher_Init(hasher);
+ assertTrue(failure == 0, "Error initializing the hasher");
+
+ parcBuffer_SetPosition(wireFormat, start);
+ uint8_t *overlay = parcBuffer_Overlay(wireFormat, 0);
+
+ failure = parcCryptoHasher_UpdateBytes(hasher, overlay, length);
+ assertTrue(failure == 0, "Error updating hasher start %zu length %zu", start, length)
+ {
+ parcBuffer_Display(wireFormat, 3);
+ }
+
+ parcBuffer_Rewind(wireFormat);
+
+ PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher);
+ return hash;
+}
+
+static PARCCryptoHash *
+_ccnxWireFormatFacadeV1_HashProtectedRegion(const CCNxTlvDictionary *dictionary, PARCCryptoHasher *hasher)
+{
+ assertNotNull(dictionary, "Parameter dictionary must be non-null");
+ assertNotNull(hasher, "Parameter hasher must be non-null");
+
+ PARCCryptoHash *hash = NULL;
+
+ if (ccnxTlvDictionary_IsValueInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedStart)) {
+ if (ccnxTlvDictionary_IsValueInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedLength)) {
+ size_t startPosition = ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedStart);
+ size_t length = ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedLength);
+
+ CCNxCodecNetworkBufferIoVec *vec = _ccnxWireFormatFacadeV1_GetIoVec(dictionary);
+ if (vec) {
+ size_t totalLength = ccnxCodecNetworkBufferIoVec_Length(vec);
+ if (startPosition + length <= totalLength) {
+ hash = _hashProtectedRegionIoVec(vec, hasher, startPosition, length);
+ }
+ } else {
+ PARCBuffer *wireFormat = _ccnxWireFormatFacadeV1_GetWireFormatBuffer(dictionary);
+ if (wireFormat) {
+ size_t totalLength = parcBuffer_Remaining(wireFormat);
+ if (startPosition + length <= totalLength) {
+ hash = _ccnxWireFormatFacadeV1_ComputeBufferHash(wireFormat, hasher, startPosition, length);
+ }
+ }
+ }
+ }
+ }
+
+ return hash;
+}
+
+
+static PARCCryptoHash *
+_ccnxWireFormatFacadeV1_ComputeContentObjectHash(CCNxTlvDictionary *dictionary)
+{
+ // This assumes the dictionary has been passed through something like the V1 packet decoder,
+ // (e.g. ccnxCodecSchemaV1PacketDecoder_Decode) and has had the protected region extents set.
+ // This will be the case for Athena. Metis has its own TLV parsing.
+
+ assertTrue(ccnxTlvDictionary_IsContentObject(dictionary) || ccnxTlvDictionary_IsManifest(dictionary), "Message must be a ContentObject or Manifest");
+
+ PARCCryptoHash *result = NULL;
+
+ if (ccnxTlvDictionary_IsValueInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ContentObjectHashRegionStart)
+ && ccnxTlvDictionary_IsValueInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ContentObjectHashRegionLength)) {
+ PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
+ size_t startPosition = ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ContentObjectHashRegionStart);
+ size_t length = ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ContentObjectHashRegionLength);
+
+ CCNxCodecNetworkBufferIoVec *vec = _ccnxWireFormatFacadeV1_GetIoVec(dictionary);
+ if (vec) {
+ size_t totalLength = ccnxCodecNetworkBufferIoVec_Length(vec);
+ if (startPosition + length <= totalLength) {
+ result = _hashProtectedRegionIoVec(vec, hasher, startPosition, length);
+ }
+ } else {
+ PARCBuffer *wireFormat = _ccnxWireFormatFacadeV1_GetWireFormatBuffer(dictionary);
+ if (wireFormat) {
+ size_t totalLength = parcBuffer_Remaining(wireFormat);
+ if (startPosition + length <= totalLength) {
+ result = _ccnxWireFormatFacadeV1_ComputeBufferHash(wireFormat, hasher, startPosition, length);
+ }
+ }
+ }
+ parcCryptoHasher_Release(&hasher);
+ }
+
+ return result; // Could be NULL
+}
+
+
+/**
+ * `CCNxWireFormatFacadeV1_Implementation` is the structure containing the pointers to the
+ * V1 schema WireFormatMessage implementation.
+ */
+CCNxWireFormatMessageInterface CCNxWireFormatFacadeV1_Implementation = {
+ .description = "CCNxWireFormatFacadeV1_Implementation",
+
+ .create = &_ccnxWireFormatFacadeV1_CreateFromV1,
+
+ .fromInterestPacketType = &_ccnxWireFormatFacadeV1_FromInterestPacketType,
+
+ .fromInterestPacketTypeIoVec = &_ccnxWireFormatFacadeV1_FromInterestPacketTypeIoVec,
+
+ .fromContentObjectPacketType = &_ccnxWireFormatFacadeV1_FromContentObjectPacketType,
+
+ .fromControlPacketType = &_ccnxWireFormatFacadeV1_FromControlPacketType,
+
+ .getWireFormatBuffer = &_ccnxWireFormatFacadeV1_GetWireFormatBuffer,
+
+ .getIoVec = &_ccnxWireFormatFacadeV1_GetIoVec,
+
+ .putWireFormatBuffer = &_ccnxWireFormatFacadeV1_PutWireFormatBuffer,
+
+ .putIoVec = &_ccnxWireFormatFacadeV1_PutIoVec,
+
+ .writeToFile = &_ccnxWireFormatFacadeV1_WriteToFile,
+
+ .setProtectedRegionStart = &_ccnxWireFormatFacadeV1_SetProtectedRegionStart,
+
+ .setProtectedRegionLength = &_ccnxWireFormatFacadeV1_SetProtectedRegionLength,
+
+ .hashProtectedRegion = &_ccnxWireFormatFacadeV1_HashProtectedRegion,
+
+ .setContentObjectHashRegionStart = &_ccnxWireFormatFacadeV1_SetContentObjectHashRegionStart,
+
+ .setContentObjectHashRegionLength = &_ccnxWireFormatFacadeV1_SetContentObjectHashRegionLength,
+
+ .computeContentObjectHash = &_ccnxWireFormatFacadeV1_ComputeContentObjectHash,
+
+ .setHopLimit = &_ccnxWireFormatFacadeV1_SetHopLimit,
+
+ .convertInterestToInterestReturn = &_ccnxWireFormatFacadeV1_ConvertInterestToInterestReturn,
+};
diff --git a/libccnx-common/ccnx/common/internal/ccnx_WireFormatFacadeV1.h b/libccnx-common/ccnx/common/internal/ccnx_WireFormatFacadeV1.h
new file mode 100755
index 00000000..cd888062
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_WireFormatFacadeV1.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * @file ccnx_WireFormatFacadeV1.h
+ * @ingroup Utility
+ *
+ * A WireFormat facade will set/get the wire format representation of a message from the
+ * dictionary.
+ *
+ * One may also create a message dictionary only with a wire format, not specifying the actual message type.
+ * This occurs mostly at the lowest layer that receives a network buffer and does not yet know what sort of message it holds.
+ *
+ * This facade is used by the Forwarder Connector to create the original dictionary
+ * at the bottom of the stack on receive. It is also used by the Codec component to set
+ * the wireformat to encode a packet.
+ *
+ * If an application has a pre-encoded packet, it can create an empty dictionary and set the wire format
+ * then send that down the stack.
+ *
+ */
+#ifndef libccnx_ccnx_WireFormatFacadeV1_h
+#define libccnx_ccnx_WireFormatFacadeV1_h
+
+
+#include <ccnx/common/internal/ccnx_WireFormatMessageInterface.h>
+
+extern CCNxWireFormatMessageInterface CCNxWireFormatFacadeV1_Implementation;
+#endif // libccnx_ccnx_WireFormatFacadeV1_h
diff --git a/libccnx-common/ccnx/common/internal/ccnx_WireFormatMessageInterface.c b/libccnx-common/ccnx/common/internal/ccnx_WireFormatMessageInterface.c
new file mode 100755
index 00000000..bb698eb4
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_WireFormatMessageInterface.c
@@ -0,0 +1,46 @@
+/*
+ * 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 <config.h>
+
+#include <LongBow/runtime.h>
+
+#include <ccnx/common/internal/ccnx_WireFormatMessageInterface.h>
+
+
+CCNxWireFormatMessageInterface *
+ccnxWireFormatMessageInterface_GetInterface(const CCNxTlvDictionary *dictionary)
+{
+ CCNxWireFormatMessageInterface *impl = NULL;
+
+ int schemaVersion = ccnxTlvDictionary_GetSchemaVersion(dictionary);
+
+ switch (schemaVersion) {
+ case CCNxTlvDictionary_SchemaVersion_V1:
+ impl = &CCNxWireFormatFacadeV1_Implementation;
+ break;
+ default:
+ trapUnexpectedState("Unknown SchemaVersion encountered in ccnxWireFormatMessageInterface_GetInterface()");
+ break;
+ }
+
+ // We do not set the implementation pointer in the dictionary here. That is only done when accessing the dictionary
+ // as a CCNxContentObject, CCNxInterest, CCNxInterestReturn, or CCNxControlMessage.
+
+ return impl;
+}
diff --git a/libccnx-common/ccnx/common/internal/ccnx_WireFormatMessageInterface.h b/libccnx-common/ccnx/common/internal/ccnx_WireFormatMessageInterface.h
new file mode 100755
index 00000000..2efc2194
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/ccnx_WireFormatMessageInterface.h
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+/**
+ * @brief The definition of the interface used to call into a CCNxWireFormatFacade implementation.
+ *
+ */
+
+#ifndef CCNx_Common_ccnx_internal_WireFormatMessageInterface_h
+#define CCNx_Common_ccnx_internal_WireFormatMessageInterface_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+
+typedef struct ccnx_wireformatmessage_interface {
+ char *description; // A human-readable label for this implementation
+
+ /** @see ccnxWireFormatMessage_Create */
+ CCNxTlvDictionary *(*create)(const PARCBuffer * wireFormat);
+
+ /** @see ccnxWireFormatMessage_FromInterestPacketType */
+ CCNxTlvDictionary *(*fromInterestPacketType)(const PARCBuffer * wireFormat);
+
+ /** @see ccnxWireFormatMessage_FromInterestPacketTypeIoVec */
+ CCNxTlvDictionary *(*fromInterestPacketTypeIoVec)(const CCNxCodecNetworkBufferIoVec * vec);
+
+ /** @see ccnxWireFormatMessage_FromContentObjectPacketType */
+ CCNxTlvDictionary *(*fromContentObjectPacketType)(const PARCBuffer * wireFormat);
+
+ /** @see ccnxWireFormatMessage_FromControlPacketType */
+ CCNxTlvDictionary *(*fromControlPacketType)(const PARCBuffer * wireFormat);
+
+ /** @see ccnxWireFormatMessage_GetWireFormatBuffer */
+ PARCBuffer *(*getWireFormatBuffer)(const CCNxTlvDictionary * dictionary);
+
+ /** @see ccnxWireFormatMessage_GetIoVec */
+ CCNxCodecNetworkBufferIoVec *(*getIoVec)(const CCNxTlvDictionary * dictionary);
+
+ /** @see ccnxWireFormatMessage_PutWireFormatBuffer */
+ bool (*putWireFormatBuffer)(CCNxTlvDictionary *dictionary, PARCBuffer *buffer);
+
+ /** @see ccnxWireFormatMessage_PutIoVec */
+ bool (*putIoVec)(CCNxTlvDictionary *dictionary, CCNxCodecNetworkBufferIoVec *vec);
+
+ /** @see ccnxWireFormatMessage_WriteToFile */
+ void (*writeToFile)(const CCNxTlvDictionary *dictionary, const char *filename);
+
+ /** @see ccnxWireFormatMessage_SetProtectedRegionStart */
+ bool (*setProtectedRegionStart)(CCNxTlvDictionary *dictionary, size_t startPosition);
+
+ /** @see ccnxWireFormatMessage_SetProtectedRegionLength */
+ bool (*setProtectedRegionLength)(CCNxTlvDictionary *dictionary, size_t length);
+
+ /** @see ccnxWireFormatMessage_SetContentObjectHashRegionStart */
+ bool (*setContentObjectHashRegionStart)(CCNxTlvDictionary *dictionary, size_t startPosition);
+
+ /** @see ccnxWireFormatMessage_SetContentObjectHashRegionLength */
+ bool (*setContentObjectHashRegionLength)(CCNxTlvDictionary *dictionary, size_t length);
+
+ /** @see ccnxWireFormatMessage_HashProtectedRegion */
+ PARCCryptoHash *(*hashProtectedRegion)(const CCNxTlvDictionary * dictionary, PARCCryptoHasher * hasher);
+
+ /** @see ccnxWireFormatMessage_SetHopLimit */
+ bool (*setHopLimit)(CCNxTlvDictionary *dictionary, uint32_t hopLimit);
+
+ /** @see ccnxWireFormatMessage_AssertValid*/
+ void (*assertValid)(const CCNxTlvDictionary *dictionary);
+
+ /** @see ccnxWireFormatMessage_CreateContentObjectHash */
+ PARCCryptoHash *(*computeContentObjectHash)(CCNxTlvDictionary * dictionary);
+
+ /** @see ccnxWireFormatMessage_ConvertInterestToInterestReturn */
+ bool (*convertInterestToInterestReturn)(CCNxTlvDictionary *dictionary, uint8_t returnCode);
+} CCNxWireFormatMessageInterface;
+
+/**
+ * The SchemaV0 WireFormatMessage implementaton
+ */
+extern CCNxWireFormatMessageInterface CCNxWireFormatFacadeV0_Implementation;
+
+/**
+ * The SchemaV1 WireFormatMessage implementaton
+ */
+extern CCNxWireFormatMessageInterface CCNxWireFormatFacadeV1_Implementation;
+
+/**
+ * Given a CCNxTlvDictionary representing a CCNxWireFormatMessage, return the address of the CCNxWireFormatMessageInterface
+ * instance that should be used to access the WireFormatMessage.
+ *
+ * @param interestDictionary - a {@link CCNxTlvDictionary} representing a CCNxInterestReturn.
+ * @return the address of the `CCNxWireFormatMessageInterface` instance that should be used to access the CCNxWireFormatMessage.
+ *
+ * Example:
+ * @code
+ * {
+ *
+ * CCNxWireFormatMessage *message = ccnxWireFormatMessage_FromInterestPacketType(schemaVersion, wireFormatBuffer);
+ *
+ * //V1 test
+ * if (ccnxWireFormatMessageInterface_GetInterface(interestReturn) == &CCNxWireFormatFacadeV1_Implementation) {
+ * printf("Using a V1 CCNxWireFormatFacadeV1_Implementation \n");
+ * }
+ *
+ * ...
+ *
+ * ccnxWireFormatMessage_Release(&message);
+ * } * @endcode
+ */
+CCNxWireFormatMessageInterface *ccnxWireFormatMessageInterface_GetInterface(const CCNxTlvDictionary *contentDictionary);
+#endif
diff --git a/libccnx-common/ccnx/common/internal/test/.gitignore b/libccnx-common/ccnx/common/internal/test/.gitignore
new file mode 100644
index 00000000..d8148318
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/.gitignore
@@ -0,0 +1,18 @@
+test_ccnx_ChunkingFacadeV0
+test_ccnx_ChunkingFacadeV1
+test_ccnx_ContentObjectFacadeV0
+test_ccnx_ContentObjectFacadeV1
+test_ccnx_ContentObjectInterface
+test_ccnx_ControlFacade
+test_ccnx_InterestFacadeV0
+test_ccnx_InterestFacadeV1
+test_ccnx_InterestInterface
+test_ccnx_InterestReturnInterface
+test_ccnx_Tlv
+test_ccnx_TlvDictionary
+test_ccnx_TlvEncodingBuffer
+test_ccnx_TlvError
+test_ccnx_ValidationFacadeV0
+test_ccnx_ValidationFacadeV1
+test_ccnx_WireFormatFacadeV0
+test_ccnx_WireFormatFacadeV1
diff --git a/libccnx-common/ccnx/common/internal/test/CMakeLists.txt b/libccnx-common/ccnx/common/internal/test/CMakeLists.txt
new file mode 100644
index 00000000..900ba031
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Enable gcov output for the tests
+add_definitions(--coverage)
+set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
+
+set(TestsExpectedToPass
+ test_ccnx_ChunkingFacadeV1
+ test_ccnx_ContentObjectFacadeV1
+ test_ccnx_ContentObjectInterface
+ test_ccnx_InterestFacadeV1
+ test_ccnx_InterestInterface
+ test_ccnx_InterestReturnFacadeV1
+ test_ccnx_InterestReturnInterface
+ test_ccnx_ManifestFacadeV1
+ test_ccnx_ManifestInterface
+ test_ccnx_TlvDictionary
+ test_ccnx_ValidationFacadeV1
+ test_ccnx_WireFormatFacadeV1
+)
+
+
+foreach(test ${TestsExpectedToPass})
+ AddTest(${test})
+endforeach()
+
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ChunkingFacade b/libccnx-common/ccnx/common/internal/test/test_ccnx_ChunkingFacade
new file mode 100755
index 00000000..0894fcbd
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ChunkingFacade
Binary files differ
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ChunkingFacadeV1.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_ChunkingFacadeV1.c
new file mode 100755
index 00000000..6f14cf47
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ChunkingFacadeV1.c
@@ -0,0 +1,261 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_ChunkingFacadeV1.c"
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+#include <inttypes.h>
+
+#include <ccnx/common/ccnx_ContentObject.h>
+#include <ccnx/common/ccnx_Interest.h>
+#include <ccnx/common/ccnx_PayloadType.h>
+
+#include <ccnx/common/internal/ccnx_ContentObjectInterface.h>
+
+typedef struct test_data {
+ CCNxName *name;
+ CCNxTlvDictionary *contentObjectV1;
+ CCNxTlvDictionary *contentObjectVFF;
+
+ CCNxTlvDictionary *interest;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->name = ccnxName_CreateFromCString("lci:/foo/bar/v1");
+
+ data->contentObjectV1 =
+ ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ data->name,
+ CCNxPayloadType_DATA, NULL);
+
+ data->contentObjectVFF = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+
+ ccnxTlvDictionary_SetMessageType_ContentObject(data->contentObjectVFF, 0xFF);
+
+ data->interest =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ data->name, 5000, NULL, NULL, 100);
+
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxName_Release(&data->name);
+ ccnxTlvDictionary_Release(&data->contentObjectV1);
+ ccnxTlvDictionary_Release(&data->contentObjectVFF);
+ ccnxTlvDictionary_Release(&data->interest);
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(ccnx_ChunkingFacade)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_ChunkingFacade)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_ChunkingFacade)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_GetEndChunkNumber_NotContentObject);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_GetEndChunkNumber_V1_With);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_GetEndChunkNumber_V1_Without);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_GetEndChunkNumber_InvalidVersion);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_HasEndChunkNumber_NotContentObject);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_HasEndChunkNumber_V1_With);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_HasEndChunkNumber_V1_Without);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_HasEndChunkNumber_InvalidVersion);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_SetEndChunkNumber_NotContentObject);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxChunkingFacade_SetEndChunkNumber_InvalidVersion);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _commonTeardown(data);
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_CASE_EXPECTS(Global, ccnxChunkingFacade_GetEndChunkNumber_NotContentObject, .event = &LongBowTrapIllegalValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxChunkingFacadeV1_GetEndChunkNumber(data->interest);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxChunkingFacade_GetEndChunkNumber_V1_With)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint64_t endChunkNumber = 5;
+
+ ccnxChunkingFacadeV1_SetEndChunkNumber(data->contentObjectV1, endChunkNumber);
+ uint64_t test = ccnxChunkingFacadeV1_GetEndChunkNumber(data->contentObjectV1);
+ assertTrue(test == endChunkNumber, "wrong value, got %" PRIu64 " expected %" PRIu64 "", test, endChunkNumber)
+ {
+ ccnxTlvDictionary_Display(data->contentObjectV1, 3);
+ }
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, ccnxChunkingFacade_GetEndChunkNumber_V1_Without, .event = &LongBowTrapIllegalValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxChunkingFacadeV1_GetEndChunkNumber(data->contentObjectV1);
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, ccnxChunkingFacade_GetEndChunkNumber_InvalidVersion, .event = &LongBowTrapIllegalValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxChunkingFacadeV1_GetEndChunkNumber(data->contentObjectVFF);
+}
+
+// ======================================================================================
+
+
+LONGBOW_TEST_CASE(Global, ccnxChunkingFacade_HasEndChunkNumber_NotContentObject)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxChunkingFacadeV1_HasEndChunkNumber(data->interest);
+ assertFalse(success, "An Interest should always return FALSE for EndChunkNumber");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxChunkingFacade_HasEndChunkNumber_V1_With)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ ccnxChunkingFacadeV1_SetEndChunkNumber(data->contentObjectV1, 5);
+ bool success = ccnxChunkingFacadeV1_HasEndChunkNumber(data->contentObjectV1);
+ assertTrue(success, "Content Object with EndChunkNumber returned false")
+ {
+ ccnxTlvDictionary_Display(data->contentObjectV1, 3);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxChunkingFacade_HasEndChunkNumber_V1_Without)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ bool success = ccnxChunkingFacadeV1_HasEndChunkNumber(data->contentObjectV1);
+ assertFalse(success, "Content Object without EndChunkNumber returned true")
+ {
+ ccnxTlvDictionary_Display(data->contentObjectV1, 3);
+ }
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, ccnxChunkingFacade_HasEndChunkNumber_InvalidVersion, .event = &LongBowTrapIllegalValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxChunkingFacadeV1_HasEndChunkNumber(data->contentObjectVFF);
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_CASE_EXPECTS(Global, ccnxChunkingFacade_SetEndChunkNumber_NotContentObject, .event = &LongBowTrapIllegalValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint64_t endChunkNumber = 7;
+ ccnxChunkingFacadeV1_SetEndChunkNumber(data->interest, endChunkNumber);
+}
+
+
+LONGBOW_TEST_CASE(Global, ccnxChunkingFacade_SetEndChunkNumber_V1)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint64_t endChunkNumber = 7;
+ bool success = ccnxChunkingFacadeV1_SetEndChunkNumber(data->contentObjectV1, endChunkNumber);
+
+ assertTrue(success, "Setting EndChunkNumber failed")
+ {
+ ccnxTlvDictionary_Display(data->contentObjectV1, 3);
+ }
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Global, ccnxChunkingFacade_SetEndChunkNumber_InvalidVersion, .event = &LongBowTrapIllegalValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxChunkingFacadeV1_SetEndChunkNumber(data->contentObjectVFF, 7);
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_ChunkingFacade);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectFacade b/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectFacade
new file mode 100755
index 00000000..073ccae4
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectFacade
Binary files differ
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectFacadeV1.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectFacadeV1.c
new file mode 100644
index 00000000..b3c6b343
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectFacadeV1.c
@@ -0,0 +1,377 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_ContentObjectFacadeV1.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+#include <inttypes.h>
+
+typedef struct test_data {
+ CCNxName *name;
+ CCNxPayloadType payloadType;
+ PARCBuffer *payload;
+
+ // a V1 dictionary but with no values set
+ CCNxTlvDictionary *contentObjectV1Empty;
+
+ // a V1 nameless Content Object
+ CCNxTlvDictionary *contentObjectV1Nameless;
+
+ // a valid V1 Content Object
+ CCNxTlvDictionary *contentObjectV1;
+ CCNxTlvDictionary *contentObjectVFF;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->name = ccnxName_CreateFromCString("lci:/foo/bar");
+ data->payloadType = CCNxPayloadType_DATA;
+
+ data->payload = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(20), 7, (uint8_t *) "payload"));
+
+ data->contentObjectV1Empty = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ data->contentObjectV1 = _ccnxContentObjectFacadeV1_CreateWithNameAndPayload(data->name, data->payloadType,
+ data->payload);
+ data->contentObjectV1Nameless = _ccnxContentObjectFacadeV1_CreateWithPayload(data->payloadType, data->payload);
+
+ data->contentObjectVFF = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+ ccnxTlvDictionary_SetMessageType_ContentObject(data->contentObjectVFF, 0xFF);
+
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxName_Release(&data->name);
+ parcBuffer_Release(&data->payload);
+
+ ccnxTlvDictionary_Release(&data->contentObjectV1Empty);
+ ccnxTlvDictionary_Release(&data->contentObjectV1);
+ ccnxTlvDictionary_Release(&data->contentObjectV1Nameless);
+ ccnxTlvDictionary_Release(&data->contentObjectVFF);
+ parcMemory_Deallocate((void **) &data);
+}
+
+
+LONGBOW_TEST_RUNNER(ccnx_ContentObjectFacade)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(ImplInterface);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_ContentObjectFacade)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_ContentObjectFacade)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_FIXTURE(ImplInterface)
+{
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_Init);
+
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetName);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetPayload);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_SetPayload);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_SetPayload_Link);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetPayloadType);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetPayloadType_Unset);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetExpiryTime);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_SetExpiryTime);
+
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_SetSignature);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetKeyId);
+
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_ToString);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_Display);
+ LONGBOW_RUN_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_Equals);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(ImplInterface)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(ImplInterface)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_Init)
+{
+ CCNxContentObjectInterface *impl = &CCNxContentObjectFacadeV1_Implementation;
+ assertNotNull(impl->createWithNameAndPayload, "Expected CreateWithNameAndPayload to be set");
+ assertNotNull(impl->createWithPayload, "Expected CreateWithPayload to be set");
+
+ assertNotNull(impl->getName, "Expected GetName to be set");
+ assertNotNull(impl->setSignature, "Expected SetSignature to be set");
+ assertNotNull(impl->getKeyId, "Expected GetKeyID to be set");
+ assertNotNull(impl->getPayload, "Expected GetPayload to be set");
+ assertNotNull(impl->getPayloadType, "Expected GetPayloadType to be set");
+
+ assertNotNull(impl->hasFinalChunkNumber, "Expected HasFinalChunkNumber to be set");
+ assertNotNull(impl->getFinalChunkNumber, "Expected GetFinalChunkNumber to be set");
+ assertNotNull(impl->setFinalChunkNumber, "Expected SetFinalChunkNumber to be set");
+
+ assertNotNull(impl->hasExpiryTime, "Expected HasExpiryTime to be set");
+ assertNotNull(impl->getExpiryTime, "Expected GetExpiryTime to be set");
+ assertNotNull(impl->setExpiryTime, "Expected SetExpiryTime to be set");
+
+ assertNotNull(impl->toString, "Expected ToString to be set");
+ assertNotNull(impl->display, "Expected Display to be set");
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetName)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxName *test = _ccnxContentObjectFacadeV1_GetName(data->contentObjectV1);
+ assertTrue(ccnxName_Equals(test, data->name), "Names do not match")
+ {
+ ccnxName_Display(test, 0);
+ ccnxName_Display(data->name, 0);
+ }
+ test = _ccnxContentObjectFacadeV1_GetName(data->contentObjectV1Nameless);
+ assertNull(test, "A nameless Content Object has no name.");
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_SetPayload)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *newPayload = parcBuffer_WrapCString("this is a new payload");
+
+ // Shouldn't be able to set it on an already initialized ContentObject.
+ // (Though this may change...)
+ assertFalse(_ccnxContentObjectFacadeV1_SetPayload(data->contentObjectV1, CCNxPayloadType_DATA, newPayload),
+ "Expected to not be able to re-assign a payload on an already initialized ContentObject");
+
+ CCNxTlvDictionary *contentObject =
+ _ccnxContentObjectFacadeV1_CreateWithNameAndPayload(data->name,
+ CCNxPayloadType_DATA,
+ NULL);
+
+
+ bool status = _ccnxContentObjectFacadeV1_SetPayload(contentObject, CCNxPayloadType_KEY, newPayload);
+ assertTrue(status, "Expected to be able to set the buffer");
+
+ PARCBuffer *testPayload = _ccnxContentObjectFacadeV1_GetPayload(contentObject);
+ assertTrue(parcBuffer_Equals(newPayload, testPayload), "payloads do not match")
+ {
+ parcBuffer_Display(newPayload, 0);
+ parcBuffer_Display(data->payload, 0);
+ }
+
+ CCNxPayloadType testType = _ccnxContentObjectFacadeV1_GetPayloadType(contentObject);
+ assertTrue(testType == CCNxPayloadType_KEY, "Expected type KEY");
+
+ parcBuffer_Release(&newPayload);
+ ccnxTlvDictionary_Release(&contentObject);
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_SetPayload_Link)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *payload = parcBuffer_WrapCString("this is a payload");
+
+ CCNxTlvDictionary *contentObject =
+ _ccnxContentObjectFacadeV1_CreateWithNameAndPayload(data->name,
+ CCNxPayloadType_LINK,
+ payload);
+
+ PARCBuffer *testPayload = _ccnxContentObjectFacadeV1_GetPayload(contentObject);
+ assertTrue(parcBuffer_Equals(payload, testPayload), "payloads do not match")
+ {
+ parcBuffer_Display(payload, 0);
+ parcBuffer_Display(testPayload, 0);
+ }
+
+ CCNxPayloadType testType = _ccnxContentObjectFacadeV1_GetPayloadType(contentObject);
+ assertTrue(testType == CCNxPayloadType_LINK, "Expected type LINK");
+
+ parcBuffer_Release(&payload);
+ ccnxTlvDictionary_Release(&contentObject);
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetPayload)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = _ccnxContentObjectFacadeV1_GetPayload(data->contentObjectV1);
+ assertTrue(parcBuffer_Equals(test, data->payload), "payloads do not match")
+ {
+ parcBuffer_Display(test, 0);
+ parcBuffer_Display(data->payload, 0);
+ }
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetPayloadType)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxPayloadType test = _ccnxContentObjectFacadeV1_GetPayloadType(data->contentObjectV1);
+ assertTrue(test == data->payloadType, "payloads do not match, got %d expected %d", test, data->payloadType)
+ {
+ ccnxTlvDictionary_Display(data->contentObjectV1, 0);
+ }
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetPayloadType_Unset)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxPayloadType test = _ccnxContentObjectFacadeV1_GetPayloadType(data->contentObjectV1Empty);
+ assertTrue(test == CCNxPayloadType_DATA, "payloads do not match, got %d expected %d", test, CCNxPayloadType_DATA)
+ {
+ ccnxTlvDictionary_Display(data->contentObjectV1, 0);
+ }
+}
+
+LONGBOW_TEST_CASE_EXPECTS(ImplInterface, ccnxContentObjectFacadeV1_ToString, .event = &LongBowTrapNotImplemented)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _ccnxContentObjectFacadeV1_ToString(data->contentObjectV1);
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_Display)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _ccnxContentObjectFacadeV1_Display(data->contentObjectV1, 0);
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_Equals)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ assertTrue(_ccnxContentObjectFacadeV1_Equals(data->contentObjectV1, data->contentObjectV1),
+ "Expected equals to be true");
+ assertFalse(_ccnxContentObjectFacadeV1_Equals(data->contentObjectV1, data->contentObjectV1Empty),
+ "Expected equals to be false");
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetExpiryTime)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint64_t truth = 12345;
+ ccnxTlvDictionary_PutInteger(data->contentObjectV1, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME, truth);
+
+ assertTrue(_ccnxContentObjectFacadeV1_HasExpiryTime(data->contentObjectV1), "Expected HasExpiryTime() to return true");
+ uint64_t expiryTime = _ccnxContentObjectFacadeV1_GetExpiryTime(data->contentObjectV1);
+ assertTrue(truth == expiryTime, "times do not match, expected %" PRIu64 ", got %" PRIu64, truth, expiryTime);
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_SetExpiryTime)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint64_t truth = 12345;
+ _ccnxContentObjectFacadeV1_SetExpiryTime(data->contentObjectV1, truth);
+ uint64_t expiryTime = _ccnxContentObjectFacadeV1_GetExpiryTime(data->contentObjectV1);
+ assertTrue(truth == expiryTime, "times do not match, expected %" PRIu64 ", got %" PRIu64, truth, expiryTime);
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_SetSignature)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar/baz");
+ PARCBuffer *payload = parcBuffer_Allocate(100);
+
+ CCNxTlvDictionary *contentObject = _ccnxContentObjectFacadeV1_CreateWithNameAndPayload(name, CCNxPayloadType_DATA,
+ payload);
+
+ PARCBuffer *keyId = parcBuffer_WrapCString("keyhash");
+ char *rawsig = "siggybits";
+ PARCBuffer *sigbits = parcBuffer_CreateFromArray((void *) rawsig, strlen(rawsig));
+
+ PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256, parcBuffer_Flip(sigbits));
+ parcBuffer_Release(&sigbits);
+
+ assertTrue(_ccnxContentObjectFacadeV1_SetSignature(contentObject, keyId, signature, NULL),
+ "Expected to be able to set the signature");
+
+ ccnxName_Release(&name);
+ parcBuffer_Release(&payload);
+ parcSignature_Release(&signature);
+ parcBuffer_Release(&keyId);
+ ccnxTlvDictionary_Release(&contentObject);
+}
+
+LONGBOW_TEST_CASE(ImplInterface, ccnxContentObjectFacadeV1_GetKeyId)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar/baz");
+ PARCBuffer *payload = parcBuffer_Allocate(100);
+
+ CCNxTlvDictionary *contentObject = _ccnxContentObjectFacadeV1_CreateWithNameAndPayload(name, CCNxPayloadType_DATA,
+ payload);
+
+ assertNull(_ccnxContentObjectFacadeV1_GetKeyId(contentObject), "Expect key ID to be NULL");
+
+ PARCBuffer *testKeyId = parcBuffer_WrapCString("keyhash");
+ char *rawsig = "siggybits";
+ PARCBuffer *sigbits = parcBuffer_CreateFromArray((void *) rawsig, strlen(rawsig));
+
+ PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256, parcBuffer_Flip(sigbits));
+ parcBuffer_Release(&sigbits);
+
+ assertTrue(_ccnxContentObjectFacadeV1_SetSignature(contentObject, testKeyId, signature, NULL),
+ "Expected to be able to set the signature");
+
+ PARCBuffer *keyId = _ccnxContentObjectFacadeV1_GetKeyId(contentObject);
+
+ assertTrue(parcBuffer_Equals(keyId, testKeyId), "Expect key ID's to be the same");
+
+ ccnxName_Release(&name);
+ parcBuffer_Release(&payload);
+ parcSignature_Release(&signature);
+ parcBuffer_Release(&keyId);
+ ccnxTlvDictionary_Release(&contentObject);
+}
+
+// ======================================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_ContentObjectFacade);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectInterface.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectInterface.c
new file mode 100755
index 00000000..65e78bed
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ContentObjectInterface.c
@@ -0,0 +1,106 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_ContentObjectInterface.c"
+
+#include <stdio.h>
+
+#include <ccnx/common/ccnx_ContentObject.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(ccnx_ContentObjectInterface)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_ContentObjectInterface)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_ContentObjectInterface)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxContentObjectInterface_GetInterface);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+
+LONGBOW_TEST_CASE(Global, ccnxContentObjectInterface_GetInterface)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+
+ CCNxContentObject *contentObjectV1 =
+ ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ name,
+ CCNxPayloadType_DATA,
+ NULL);
+
+ assertTrue(ccnxContentObjectInterface_GetInterface(contentObjectV1) == &CCNxContentObjectFacadeV1_Implementation,
+ "Expected V1 Implementation");
+
+ // Now unset the pointer and see if it gets derived properly.
+ ccnxTlvDictionary_SetMessageInterface(contentObjectV1, NULL);
+ assertTrue(ccnxContentObjectInterface_GetInterface(contentObjectV1) == &CCNxContentObjectFacadeV1_Implementation,
+ "Expected V1 Implementation");
+
+
+ ccnxName_Release(&name);
+ ccnxContentObject_Release(&contentObjectV1);
+}
+
+
+// ======================================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_ContentObjectInterface);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestFacadeV1.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestFacadeV1.c
new file mode 100755
index 00000000..477b963d
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestFacadeV1.c
@@ -0,0 +1,334 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_InterestFacadeV1.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/ccnx_Interest.h>
+
+typedef struct test_data {
+ CCNxTlvDictionary *interest;
+
+ CCNxName *name;
+ PARCBuffer *keyid;
+ PARCBuffer *contentObjectHash;
+ PARCBuffer *payload;
+
+ // allocated data
+ uint8_t keyidArray[32];
+ uint8_t contentObjectHashArray[32];
+ uint8_t payloadArray[128];
+
+ uint32_t lifetime;
+ uint32_t hoplimit;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+ data->name = ccnxName_CreateFromCString("lci:/once/upon/a/time");
+
+ for (int i = 0; i < 32; i++) {
+ data->keyidArray[i] = i * 7;
+ data->contentObjectHashArray[i] = i * 11;
+ }
+
+ for (int i = 0; i < 128; i++) {
+ data->payloadArray[i] = i * 13;
+ }
+
+ data->keyid = parcBuffer_Wrap(data->keyidArray, 32, 0, 32);
+ data->contentObjectHash = parcBuffer_Wrap(data->contentObjectHashArray, 32, 0, 32);
+ data->payload = parcBuffer_Wrap(data->payloadArray, 128, 0, 128);
+
+ data->lifetime = 900;
+ data->hoplimit = 77;
+
+ data->interest = _ccnxInterestFacadeV1_Create(data->name,
+ data->lifetime,
+ data->keyid,
+ data->contentObjectHash,
+ data->hoplimit);
+
+ _ccnxInterestFacadeV1_SetPayload(data->interest, data->payload);
+
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxName_Release(&data->name);
+ parcBuffer_Release(&data->keyid);
+ parcBuffer_Release(&data->contentObjectHash);
+ parcBuffer_Release(&data->payload);
+ ccnxTlvDictionary_Release(&data->interest);
+
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(ccnx_InterestFacadeV1)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Performance);
+
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_InterestFacadeV1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_InterestFacadeV1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ========================================================================================
+
+LONGBOW_TEST_FIXTURE(Performance)
+{
+ LONGBOW_RUN_TEST_CASE(Performance, newfangled);
+// LONGBOW_RUN_TEST_CASE(Performance, oldtimey);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Performance)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Performance)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Performance, newfangled)
+{
+ uint8_t keyidArray[32];
+ for (int i = 0; i < 32; i++) {
+ keyidArray[i] = i;
+ }
+
+ PARCBuffer *keyid = parcBuffer_Wrap(keyidArray, 32, 0, 32);
+ CCNxName *name = ccnxName_CreateFromCString("lci:/dark/and/stormy/bits");
+
+ struct timeval t0, t1;
+ unsigned trials = 10000;
+ gettimeofday(&t0, NULL);
+ for (int i = 0; i < trials; i++) {
+ CCNxTlvDictionary *interest = _ccnxInterestFacadeV1_Create(name,
+ CCNxInterestDefault_LifetimeMilliseconds,
+ keyid,
+ NULL,
+ 0x45);
+
+ ccnxTlvDictionary_Release(&interest);
+ }
+ gettimeofday(&t1, NULL);
+ timersub(&t1, &t0, &t1);
+ double seconds = t1.tv_sec + t1.tv_usec * 1E-6;
+ printf("\nNewFangled iterations %u seconds %.3f msg/sec %.3f\n", trials, seconds, trials / seconds);
+
+ ccnxName_Release(&name);
+ parcBuffer_Release(&keyid);
+}
+
+
+// ========================================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_CreateSimple);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_GetContentObjectHash);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_GetHopLimit);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_GetInterestLifetime);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_GetName);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_GetPayload);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_GetPublisherPublicKeyDigest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_AssertValid);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_Display);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestFacadeV1_Equals);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_CreateSimple)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *interest = _ccnxInterestFacadeV1_CreateSimple(data->name);
+
+ CCNxName *test = _ccnxInterestFacadeV1_GetName(interest);
+ assertTrue(ccnxName_Equals(test, data->name), "Names do not match");
+ ccnxTlvDictionary_Release(&interest);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_GetContentObjectHash)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = _ccnxInterestFacadeV1_GetContentObjectHashRestriction(data->interest);
+ assertTrue(parcBuffer_Equals(test, data->contentObjectHash), "ContentObjectHashes do not match")
+ {
+ printf("\ngot : \n"); parcBuffer_Display(test, 3);
+ printf("\nexpected: \n"); parcBuffer_Display(data->contentObjectHash, 3);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_GetHopLimit)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ unsigned test = (unsigned) _ccnxInterestFacadeV1_GetHopLimit(data->interest);
+ assertTrue(test == data->hoplimit, "Wrong hoplimit: got %u expected %u", test, data->hoplimit);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_GetInterestLifetime)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ unsigned test = (unsigned) _ccnxInterestFacadeV1_GetLifetime(data->interest);
+ assertTrue(test == data->lifetime, "Wrong lifetime: got %u expected %u", test, data->lifetime);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_AssertValid)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _ccnxInterestFacadeV1_Display(data->interest, 4);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_Display)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _ccnxInterestFacadeV1_AssertValid(data->interest);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_GetName)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxName *test = _ccnxInterestFacadeV1_GetName(data->interest);
+ assertTrue(ccnxName_Equals(test, data->name), "Names do not match")
+ {
+ printf("\ngot : \n"); ccnxName_Display(test, 3);
+ printf("\nexpected: \n"); ccnxName_Display(data->name, 3);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_GetPublisherPublicKeyDigest)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = _ccnxInterestFacadeV1_GetKeyIdRestriction(data->interest);
+ assertTrue(parcBuffer_Equals(test, data->keyid), "KeyIDs do not match")
+ {
+ printf("\ngot : \n"); parcBuffer_Display(test, 3);
+ printf("\nexpected: \n"); parcBuffer_Display(data->keyid, 3);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_GetPayload)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = _ccnxInterestFacadeV1_GetPayload(data->interest);
+ assertTrue(parcBuffer_Equals(test, data->payload), "Payloads do not match")
+ {
+ printf("\ngot : \n"); parcBuffer_Display(test, 3);
+ printf("\nexpected: \n"); parcBuffer_Display(data->payload, 3);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestFacadeV1_Equals)
+{
+ CCNxName *name1 = ccnxName_CreateFromCString("lci:/name/1");
+ CCNxName *name2 = ccnxName_CreateFromCString("lci:/name/2");
+
+ CCNxTlvDictionary *x = _ccnxInterestFacadeV1_CreateSimple(name1); // same
+ CCNxTlvDictionary *y = _ccnxInterestFacadeV1_CreateSimple(name1); // same
+ CCNxTlvDictionary *z = _ccnxInterestFacadeV1_CreateSimple(name1); // same
+
+ CCNxTlvDictionary *diff = _ccnxInterestFacadeV1_CreateSimple(name2); // different
+
+ assertEqualsContract(_ccnxInterestFacadeV1_Equals, x, y, z, diff);
+
+ ccnxTlvDictionary_Release(&x);
+ ccnxTlvDictionary_Release(&y);
+ ccnxTlvDictionary_Release(&z);
+ ccnxTlvDictionary_Release(&diff);
+
+ ccnxName_Release(&name1);
+ ccnxName_Release(&name2);
+}
+
+
+// ========================================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_InterestFacadeV1);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestInterface.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestInterface.c
new file mode 100755
index 00000000..67bde1f5
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestInterface.c
@@ -0,0 +1,107 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+
+#include <config.h>
+#include <LongBow/unit-test.h>
+
+#include "../ccnx_InterestInterface.c"
+
+#include <stdio.h>
+
+#include <ccnx/common/ccnx_Interest.h>
+#include <ccnx/common/internal/ccnx_InterestDefault.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+
+LONGBOW_TEST_RUNNER(ccnx_InterestInterface)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_InterestInterface)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_InterestInterface)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestInterface_GetInterface);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+
+LONGBOW_TEST_CASE(Global, ccnxInterestInterface_GetInterface)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+
+ CCNxInterest *interestV1 =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ name,
+ CCNxInterestDefault_LifetimeMilliseconds,
+ NULL,
+ NULL,
+ CCNxInterestDefault_HopLimit);
+
+ CCNxInterestInterface *interface = ccnxInterestInterface_GetInterface(interestV1);
+ assertTrue(interface == &CCNxInterestFacadeV1_Implementation, "Expected V1 Implementation");
+
+ ccnxName_Release(&name);
+ ccnxInterest_Release(&interestV1);
+}
+
+
+// ======================================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_InterestInterface);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestReturnFacadeV1.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestReturnFacadeV1.c
new file mode 100755
index 00000000..1372a750
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestReturnFacadeV1.c
@@ -0,0 +1,168 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_InterestReturnFacadeV1.c"
+#include "../ccnx_InterestFacadeV1.h"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/ccnx_Interest.h>
+#include <ccnx/common/ccnx_InterestReturn.h>
+#include <ccnx/common/ccnx_PayloadType.h>
+
+typedef struct test_data {
+ CCNxTlvDictionary *interest;
+
+ CCNxName *name;
+ PARCBuffer *keyid;
+ PARCBuffer *contentObjectHash;
+ PARCBuffer *payload;
+
+ // allocated data
+ uint8_t keyidArray[32];
+ uint8_t contentObjectHashArray[32];
+ uint8_t payloadArray[128];
+
+ uint32_t lifetime;
+ uint32_t hoplimit;
+ CCNxPayloadType payloadType;
+} TestData;
+
+
+LONGBOW_TEST_RUNNER(ccnx_InterestReturnFacadeV1)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_InterestReturnFacadeV1)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_InterestReturnFacadeV1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ========================================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestReturnFacadeV1_Create);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestReturnFacadeV1_GetReturnCode);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%lu) returned NULL", sizeof(TestData));
+ data->name = ccnxName_CreateFromCString("lci:/once/upon/a/time");
+
+ for (int i = 0; i < 32; i++) {
+ data->keyidArray[i] = i * 7;
+ data->contentObjectHashArray[i] = i * 11;
+ }
+
+ for (int i = 0; i < 128; i++) {
+ data->payloadArray[i] = i * 13;
+ }
+
+ data->keyid = parcBuffer_Wrap(data->keyidArray, 32, 0, 32);
+ data->contentObjectHash = parcBuffer_Wrap(data->contentObjectHashArray, 32, 0, 32);
+ data->payloadType = CCNxPayloadType_DATA;
+ data->payload = parcBuffer_Wrap(data->payloadArray, 128, 0, 128);
+
+ data->lifetime = 900;
+ data->hoplimit = 77;
+
+ data->interest = ccnxInterest_Create(data->name,
+ data->lifetime,
+ data->keyid,
+ data->contentObjectHash);
+
+ ccnxInterest_SetPayload(data->interest, data->payload);
+
+ longBowTestCase_SetClipBoardData(testCase, data);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxName_Release(&data->name);
+ parcBuffer_Release(&data->keyid);
+ parcBuffer_Release(&data->contentObjectHash);
+ parcBuffer_Release(&data->payload);
+ ccnxTlvDictionary_Release(&data->interest);
+
+ parcMemory_Deallocate((void **) &data);
+
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_TEARDOWN_FAILED;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestReturnFacadeV1_Create)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxTlvDictionary *interestReturn =
+ _ccnxInterestReturnFacadeV1_Create(data->interest, CCNxInterestReturn_ReturnCode_NoRoute);
+ assertNotNull(interestReturn, "Expect non-NULL interestReturn");
+ _ccnxInterestReturnFacadeV1_AssertValid(interestReturn);
+
+ CCNxInterestReturn_ReturnCode code = _ccnxInterestReturnFacadeV1_GetReturnCode(interestReturn);
+ assertTrue((CCNxInterestReturn_ReturnCode_NoRoute == code), "InterestReturn wrong Return Code");
+ ccnxTlvDictionary_Release(&interestReturn);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxInterestReturnFacadeV1_GetReturnCode)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxTlvDictionary *interestReturn =
+ _ccnxInterestReturnFacadeV1_Create(data->interest, CCNxInterestReturn_ReturnCode_NoRoute);
+ _ccnxInterestReturnFacadeV1_AssertValid(interestReturn);
+
+ CCNxInterestReturn_ReturnCode code =
+ _ccnxInterestReturnFacadeV1_GetReturnCode(interestReturn);
+
+ assertTrue((CCNxInterestReturn_ReturnCode_NoRoute == code), "InterestReturn wrong Return Code");
+ ccnxTlvDictionary_Release(&interestReturn);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_InterestReturnFacadeV1);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestReturnInterface.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestReturnInterface.c
new file mode 100755
index 00000000..a22ab4e9
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_InterestReturnInterface.c
@@ -0,0 +1,112 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_InterestReturnInterface.c"
+
+#include <ccnx/common/ccnx_InterestReturn.h>
+#include <ccnx/common/internal/ccnx_InterestDefault.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <stdio.h>
+
+LONGBOW_TEST_RUNNER(ccnx_InterestReturnInterface)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_InterestReturnInterface)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_InterestReturnInterface)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxInterestReturnInterface_GetImplementation);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+
+LONGBOW_TEST_CASE(Global, ccnxInterestReturnInterface_GetImplementation)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+
+ CCNxInterest *interestV1 =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ name,
+ CCNxInterestDefault_LifetimeMilliseconds,
+ NULL,
+ NULL,
+ CCNxInterestDefault_HopLimit);
+ ccnxName_Release(&name);
+
+ CCNxInterestReturn *interestReturn = ccnxInterestReturn_Create(interestV1, CCNxInterestReturn_ReturnCode_Congestion);
+
+ assertTrue(ccnxInterestReturnInterface_GetInterface(interestReturn) == &CCNxInterestReturnFacadeV1_Implementation,
+ "Expected V1 Implementation");
+
+ // Now unset the pointer and see if it gets derived properly.
+ ccnxTlvDictionary_SetMessageInterface(interestReturn, NULL);
+
+ assertTrue(ccnxInterestReturnInterface_GetInterface(interestReturn) == &CCNxInterestReturnFacadeV1_Implementation,
+ "Expected V1 Implementation");
+
+ ccnxInterestReturn_Release(&interestReturn);
+ ccnxInterest_Release(&interestV1);
+}
+
+
+// ======================================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_InterestReturnInterface);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ManifestFacadeV1.c.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_ManifestFacadeV1.c.c
new file mode 100644
index 00000000..253b8e5a
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ManifestFacadeV1.c.c
@@ -0,0 +1,223 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_ManifestFacadeV1.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_Memory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/ccnx_Manifest.h>
+
+typedef struct test_data {
+ CCNxTlvDictionary *manifest;
+
+ CCNxName *name;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->name = ccnxName_CreateFromCString("lci:/once/upon/a/time");
+ data->manifest = _ccnxManifestFacadeV1_Create(data->name);
+
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxName_Release(&data->name);
+ ccnxTlvDictionary_Release(&data->manifest);
+
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(ccnx_ManifestFacadeV1)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_ManifestFacadeV1)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_ManifestFacadeV1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ========================================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxManifestFacadeV1_Create);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxManifestFacadeV1_GetName);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxManifestFacadeV1_AddHashGroup);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxManifestFacadeV1_GetHashGroup);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxManifestFacadeV1_Equals);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxManifestFacadeV1_Create)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *manifest = _ccnxManifestFacadeV1_Create(data->name);
+
+ const CCNxName *test = _ccnxManifestFacadeV1_GetName(manifest);
+ assertTrue(ccnxName_Equals(test, data->name), "Names do not match");
+ ccnxTlvDictionary_Release(&manifest);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxManifestFacadeV1_AddHashGroup)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *manifest = _ccnxManifestFacadeV1_Create(data->name);
+
+ int actual = 0;
+ int numberOfGroups = _ccnxManifestFacadeV1_GetNumberOfHashGroups(manifest);
+ assertTrue(numberOfGroups == actual, "Expected %d, got %d", actual, numberOfGroups);
+
+ CCNxManifestHashGroup *hashGroup = ccnxManifestHashGroup_Create();
+ _ccnxManifestFacadeV1_AddHashGroup(manifest, hashGroup);
+ actual++;
+ numberOfGroups = _ccnxManifestFacadeV1_GetNumberOfHashGroups(manifest);
+
+ assertTrue(numberOfGroups == actual, "Expected %d, got %d", actual, numberOfGroups);
+
+ ccnxManifestHashGroup_Release(&hashGroup);
+ ccnxTlvDictionary_Release(&manifest);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxManifestFacadeV1_GetHashGroup)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *manifest = _ccnxManifestFacadeV1_Create(data->name);
+
+ CCNxManifestHashGroup *hashGroup = ccnxManifestHashGroup_Create();
+ _ccnxManifestFacadeV1_AddHashGroup(manifest, hashGroup);
+
+ CCNxManifestHashGroup *firstGroup = _ccnxManifestFacadeV1_GetHashGroup(manifest, 0);
+ assertTrue(ccnxManifestHashGroup_Equals(hashGroup, firstGroup), "Expected the HashGroups to be equal");
+
+ ccnxManifestHashGroup_Release(&hashGroup);
+ ccnxManifestHashGroup_Release(&firstGroup);
+ ccnxTlvDictionary_Release(&manifest);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxManifestFacadeV1_GetNumberOfHashGroups)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *manifest = _ccnxManifestFacadeV1_Create(data->name);
+
+ size_t numberOfGroups = _ccnxManifestFacadeV1_GetNumberOfHashGroups(manifest);
+ assertTrue(numberOfGroups == 1, "Expected 1 group, got %zu", numberOfGroups);
+ ccnxTlvDictionary_Release(&manifest);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxManifestFacadeV1_GetName)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ const CCNxName *test = _ccnxManifestFacadeV1_GetName(data->manifest);
+ assertTrue(ccnxName_Equals(test, data->name), "Names do not match")
+ {
+ printf("\ngot : \n"); ccnxName_Display(test, 3);
+ printf("\nexpected: \n"); ccnxName_Display(data->name, 3);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxManifestFacadeV1_Equals)
+{
+ CCNxName *name1 = ccnxName_CreateFromCString("lci:/name/1");
+ CCNxName *name2 = ccnxName_CreateFromCString("lci:/name/2");
+
+ CCNxTlvDictionary *x = _ccnxManifestFacadeV1_Create(name1);
+ CCNxTlvDictionary *y = _ccnxManifestFacadeV1_Create(name1);
+ CCNxTlvDictionary *z = _ccnxManifestFacadeV1_Create(name1);
+
+ CCNxTlvDictionary *diff = _ccnxManifestFacadeV1_Create(name2);
+
+ assertEqualsContract(_ccnxManifestFacadeV1_Equals, x, y, z, diff, NULL);
+
+ ccnxTlvDictionary_Release(&x);
+ ccnxTlvDictionary_Release(&y);
+ ccnxTlvDictionary_Release(&z);
+ ccnxTlvDictionary_Release(&diff);
+
+ ccnxName_Release(&name1);
+ ccnxName_Release(&name2);
+}
+
+// ========================================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_ManifestFacadeV1);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ManifestInterface.c.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_ManifestInterface.c.c
new file mode 100755
index 00000000..42ce095f
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ManifestInterface.c.c
@@ -0,0 +1,100 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_ManifestInterface.c"
+
+#include <ccnx/common/ccnx_Manifest.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <stdio.h>
+
+LONGBOW_TEST_RUNNER(ccnx_ManifestInterface)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_ManifestInterface)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_ManifestInterface)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxManifestInterface_GetImplementation);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ======================================================================================
+
+
+LONGBOW_TEST_CASE(Global, ccnxManifestInterface_GetImplementation)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+
+ CCNxManifest *manifestV1 = ccnxManifest_Create(name);
+ ccnxName_Release(&name);
+
+ assertTrue(ccnxManifestInterface_GetInterface(manifestV1) == &CCNxManifestFacadeV1_Interface, "Expected V1 Implementation");
+
+ // Now unset the pointer and see if it gets derived properly.
+ ccnxTlvDictionary_SetMessageInterface(manifestV1, NULL);
+
+ assertTrue(ccnxManifestInterface_GetInterface(manifestV1) == &CCNxManifestFacadeV1_Interface, "Expected V1 Implementation");
+
+ ccnxManifest_Release(&manifestV1);
+}
+
+
+// ======================================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_ManifestInterface);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_TlvDictionary.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_TlvDictionary.c
new file mode 100755
index 00000000..51936d96
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_TlvDictionary.c
@@ -0,0 +1,1142 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_TlvDictionary.c"
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <ccnx/common/internal/ccnx_ContentObjectInterface.h>
+#include <ccnx/common/internal/ccnx_InterestInterface.h>
+
+#include <LongBow/unit-test.h>
+
+typedef struct test_data {
+ CCNxTlvDictionary *dictionary;
+ size_t fastArraySize;
+ size_t listSize;
+} TestData;
+
+typedef enum {
+ SchemaFree = 0,
+ SchemaBuffer = 1,
+ SchemaInteger = 2,
+ SchemaIoVec = 3,
+ SchemaJson = 4,
+ SchemaName = 5,
+ SchemaEnd = 6,
+} TestSchema;
+
+static CCNxCodecNetworkBufferIoVec *
+createIoVec(void)
+{
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL);
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+ return vec;
+}
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+ data->fastArraySize = SchemaEnd + 2;
+ data->listSize = SchemaEnd + 10;
+ data->dictionary = ccnxTlvDictionary_Create(data->fastArraySize, data->listSize);
+
+ // populate the know test vectors
+ PARCBuffer *buffer = parcBuffer_Allocate(5);
+ ccnxTlvDictionary_PutBuffer(data->dictionary, SchemaBuffer, buffer);
+ parcBuffer_Release(&buffer);
+
+ ccnxTlvDictionary_PutInteger(data->dictionary, SchemaInteger, 42);
+
+ CCNxCodecNetworkBufferIoVec *vec = createIoVec();
+ ccnxTlvDictionary_PutIoVec(data->dictionary, SchemaIoVec, vec);
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+
+ PARCJSON *json = parcJSON_ParseString("{\"KEY\": \"VALUE\"}");
+ ccnxTlvDictionary_PutJson(data->dictionary, SchemaJson, json);
+ parcJSON_Release(&json);
+
+ CCNxName *name = ccnxName_CreateFromCString("lci:/great/gatsby");
+ ccnxTlvDictionary_PutName(data->dictionary, SchemaName, name);
+ ccnxName_Release(&name);
+
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxTlvDictionary_Release(&data->dictionary);
+ parcMemory_Deallocate((void **) &data);
+}
+
+// =============================================================
+
+LONGBOW_TEST_RUNNER(rta_TlvDictionary)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(KnownKeys);
+ LONGBOW_RUN_TEST_FIXTURE(UnknownKeys);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+
+ // type specific tests
+ LONGBOW_RUN_TEST_FIXTURE(Buffer);
+ LONGBOW_RUN_TEST_FIXTURE(Integer);
+ LONGBOW_RUN_TEST_FIXTURE(IoVec);
+ LONGBOW_RUN_TEST_FIXTURE(Json);
+ LONGBOW_RUN_TEST_FIXTURE(Name);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(rta_TlvDictionary)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(rta_TlvDictionary)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// =============================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_Performance);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_Create);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_Release);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_SetMessageType_ContentObject);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_SetMessageType_Interest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_SetMessageType_Control);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_SetMessageType_InterestReturn);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_SetGetMessageTypeImplementation);
+
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvDictionary_ShallowCopy);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_Performance)
+{
+ int reps = 100000;
+ struct timeval t0, t1;
+ gettimeofday(&t0, NULL);
+ for (int i = 0; i < reps; i++) {
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 20);
+ ccnxTlvDictionary_Release(&dictionary);
+ }
+ gettimeofday(&t1, NULL);
+ timersub(&t1, &t0, &t1);
+ double seconds = t1.tv_sec + t1.tv_usec * 1E-6;
+
+ printf("time %.6f seconds, tps = %.2f\n", seconds, (double) reps / seconds);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_Acquire)
+{
+ CCNxTlvDictionary *first = ccnxTlvDictionary_Create(10, 20);
+ CCNxTlvDictionary *second = ccnxTlvDictionary_Acquire(first);
+
+ assertTrue(parcObject_GetReferenceCount(first) == 2, "Wrong ref count, got %" PRIu64 " expected %u", parcObject_GetReferenceCount(first), 2);
+
+ ccnxTlvDictionary_Release(&second);
+ ccnxTlvDictionary_Release(&first);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_Create)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(20, 30);
+ assertNotNull(dictionary, "Got null dictionary from Create");
+ assertNotNull(dictionary->directArray, "DirectArray is null");
+ assertNotNull(dictionary->fixedListHeads, "fixedListHeads is null");
+
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_Release)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(1, 1);
+ ccnxTlvDictionary_Release(&dictionary);
+ assertNull(dictionary, "Release did not null argument");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_SetMessageType_ContentObject)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(1, 1);
+ ccnxTlvDictionary_SetMessageType_ContentObject(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ assertTrue(ccnxTlvDictionary_IsContentObject(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsControl(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsInterest(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsInterestReturn(dictionary), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(dictionary) == CCNxTlvDictionary_SchemaVersion_V1, "Wrong schema type");
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_SetMessageType_Interest)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(1, 1);
+ ccnxTlvDictionary_SetMessageType_Interest(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ assertFalse(ccnxTlvDictionary_IsContentObject(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsControl(dictionary), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_IsInterest(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsInterestReturn(dictionary), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(dictionary) == CCNxTlvDictionary_SchemaVersion_V1, "Wrong schema type");
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_SetMessageType_Control)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(1, 1);
+ ccnxTlvDictionary_SetMessageType_Control(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ assertFalse(ccnxTlvDictionary_IsContentObject(dictionary), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_IsControl(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsInterest(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsInterestReturn(dictionary), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(dictionary) == CCNxTlvDictionary_SchemaVersion_V1, "Wrong schema type");
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_SetMessageType_InterestReturn)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(1, 1);
+ ccnxTlvDictionary_SetMessageType_InterestReturn(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ assertFalse(ccnxTlvDictionary_IsContentObject(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsControl(dictionary), "Wrong message type");
+ assertFalse(ccnxTlvDictionary_IsInterest(dictionary), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_IsInterestReturn(dictionary), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(dictionary) == CCNxTlvDictionary_SchemaVersion_V1, "Wrong schema type");
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_SetGetMessageTypeImplementation)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(1, 1);
+ void *impl = ccnxTlvDictionary_GetMessageInterface(dictionary);
+
+ assertNull(impl, "Expected a NULL implementation by default");
+
+ ccnxTlvDictionary_SetMessageInterface(dictionary, &CCNxContentObjectFacadeV1_Implementation);
+ assertTrue(ccnxTlvDictionary_GetMessageInterface(dictionary) == &CCNxContentObjectFacadeV1_Implementation,
+ "Expected CCNxContentObjectFacadeV1_Implementation");
+
+ ccnxTlvDictionary_SetMessageInterface(dictionary, &CCNxContentObjectFacadeV1_Implementation);
+ assertTrue(ccnxTlvDictionary_GetMessageInterface(dictionary) == &CCNxContentObjectFacadeV1_Implementation,
+ "Expected CCNxContentObjectFacadeV1_Implementation");
+
+ ccnxTlvDictionary_SetMessageInterface(dictionary, &CCNxInterestFacadeV1_Implementation);
+ assertTrue(ccnxTlvDictionary_GetMessageInterface(dictionary) == &CCNxInterestFacadeV1_Implementation,
+ "Expected CCNxInterestFacadeV1_Implementation");
+
+ ccnxTlvDictionary_SetMessageInterface(dictionary, &CCNxInterestFacadeV1_Implementation);
+ assertTrue(ccnxTlvDictionary_GetMessageInterface(dictionary) == &CCNxInterestFacadeV1_Implementation,
+ "Expected CCNxInterestFacadeV1_Implementation");
+
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_Equals)
+{
+ CCNxTlvDictionary *a = ccnxTlvDictionary_Create(1, 1);
+ CCNxTlvDictionary *b = ccnxTlvDictionary_Create(1, 1);
+ CCNxTlvDictionary *c = ccnxTlvDictionary_Create(1, 1);
+
+ ccnxTlvDictionary_SetMessageType_Interest(a, CCNxTlvDictionary_SchemaVersion_V1);
+ ccnxTlvDictionary_SetMessageType_Interest(b, CCNxTlvDictionary_SchemaVersion_V1);
+ ccnxTlvDictionary_SetMessageType_Interest(c, CCNxTlvDictionary_SchemaVersion_V1);
+
+ CCNxTlvDictionary *diffArraySize = ccnxTlvDictionary_Create(2, 1);
+ CCNxTlvDictionary *diffListSize = ccnxTlvDictionary_Create(1, 2);
+ CCNxTlvDictionary *diffType = ccnxTlvDictionary_Create(1, 1);
+ ccnxTlvDictionary_SetMessageType_Control(diffType, CCNxTlvDictionary_SchemaVersion_V1);
+
+ CCNxTlvDictionary *diffType2 = ccnxTlvDictionary_Create(1, 1);
+ ccnxTlvDictionary_SetMessageType_ContentObject(diffType2, CCNxTlvDictionary_SchemaVersion_V1);
+
+ assertEqualsContract(ccnxTlvDictionary_Equals, a, b, c, diffArraySize, diffListSize, diffType, diffType2, NULL);
+
+ ccnxTlvDictionary_Release(&diffType2);
+ ccnxTlvDictionary_Release(&diffType);
+ ccnxTlvDictionary_Release(&diffListSize);
+ ccnxTlvDictionary_Release(&diffArraySize);
+ ccnxTlvDictionary_Release(&c);
+ ccnxTlvDictionary_Release(&b);
+ ccnxTlvDictionary_Release(&a);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvDictionary_ShallowCopy)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxTlvDictionary *a = data->dictionary;
+
+ PARCBuffer *buffer = parcBuffer_WrapCString("Some Stuff");
+ ccnxTlvDictionary_PutListBuffer(a, SchemaEnd, 23, buffer);
+ parcBuffer_Release(&buffer);
+
+ CCNxTlvDictionary *b = ccnxTlvDictionary_ShallowCopy(a);
+
+ assertTrue(ccnxTlvDictionary_Equals(a, b), "Expected Dictionaries to be Equal after ShallowCopy");
+
+ ccnxTlvDictionary_Release(&b);
+}
+
+// ================================================================
+
+LONGBOW_TEST_FIXTURE(KnownKeys)
+{
+ LONGBOW_RUN_TEST_CASE(KnownKeys, ccnxTlvDictionary_Get_Exists);
+ LONGBOW_RUN_TEST_CASE(KnownKeys, ccnxTlvDictionary_Get_NotExists);
+ LONGBOW_RUN_TEST_CASE(KnownKeys, ccnxTlvDictionary_Put_Unique);
+ LONGBOW_RUN_TEST_CASE(KnownKeys, ccnxTlvDictionary_Put_Duplicate);
+
+ LONGBOW_RUN_TEST_CASE(KnownKeys, ccnxTlvDictionary_PutList_Unique);
+ LONGBOW_RUN_TEST_CASE(KnownKeys, ccnxTlvDictionary_PutList_Duplicate);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(KnownKeys)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(KnownKeys)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(KnownKeys, ccnxTlvDictionary_Get_Exists)
+{
+ uint32_t key = SchemaEnd;
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+
+ ccnxTlvDictionary_PutBuffer(data->dictionary, key, buffer);
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(data->dictionary, key);
+ assertTrue(test == buffer, "Get value wrong, got %p expected %p", (void *) test, (void *) buffer);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(KnownKeys, ccnxTlvDictionary_Get_NotExists)
+{
+ uint32_t key = SchemaEnd;
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ ccnxTlvDictionary_PutBuffer(data->dictionary, key, buffer);
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(data->dictionary, key + 1);
+ assertNull(test, "Get for missing key should return null");
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(KnownKeys, ccnxTlvDictionary_Put_Unique)
+{
+ uint32_t key = SchemaEnd;
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ bool success = ccnxTlvDictionary_PutBuffer(data->dictionary, key, buffer);
+ assertTrue(success, "Put returned false adding a unique key");
+ parcBuffer_Release(&buffer);
+
+ // one extra test particular to it being in the fast array
+ assertTrue(data->dictionary->directArray[key].entryType == ENTRY_BUFFER, "Not buffer type, got %d", data->dictionary->directArray[key].entryType);
+ assertNotNull(data->dictionary->directArray[key]._entry.buffer, "They fast array entry for key is null");
+}
+
+LONGBOW_TEST_CASE(KnownKeys, ccnxTlvDictionary_Put_Duplicate)
+{
+ uint32_t key = SchemaEnd;
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ ccnxTlvDictionary_PutBuffer(data->dictionary, key, buffer);
+ bool success = ccnxTlvDictionary_PutBuffer(data->dictionary, key, buffer);
+ assertFalse(success, "Put returned true adding a duplicate key");
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(KnownKeys, ccnxTlvDictionary_PutList_Unique)
+{
+ uint32_t listKey = SchemaEnd;
+ uint32_t bufferKey = 1000;
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ bool success = ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, bufferKey, buffer);
+ assertTrue(success, "Put returned false adding a unique key");
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(KnownKeys, ccnxTlvDictionary_PutList_Duplicate)
+{
+ uint32_t listKey = SchemaEnd;
+ uint32_t bufferKey = 1000;
+
+ // its ok to have duplicates of the custom keys
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, bufferKey, buffer);
+ bool success = ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, bufferKey, buffer);
+ assertTrue(success, "Put returned false adding a duplicate key to list");
+ parcBuffer_Release(&buffer);
+}
+
+// ================================================================
+
+LONGBOW_TEST_FIXTURE(UnknownKeys)
+{
+ LONGBOW_RUN_TEST_CASE(UnknownKeys, ccnxTlvDictionary_PutList_Unique);
+ LONGBOW_RUN_TEST_CASE(UnknownKeys, ccnxTlvDictionary_PutList_Duplicate);
+
+ LONGBOW_RUN_TEST_CASE(UnknownKeys, ccnxTlvDictionary_ListGetByPosition);
+ LONGBOW_RUN_TEST_CASE(UnknownKeys, ccnxTlvDictionary_ListGetByType);
+ LONGBOW_RUN_TEST_CASE(UnknownKeys, ccnxTlvDictionary_ListSize);
+ LONGBOW_RUN_TEST_CASE(UnknownKeys, ccnxTlvDictionary_ListEquals);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(UnknownKeys)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(UnknownKeys)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(UnknownKeys, ccnxTlvDictionary_PutList_Unique)
+{
+ uint32_t listKey = FIXED_LIST_LENGTH + 1;
+ uint32_t bufferKey = 1000;
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ bool success = ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, bufferKey, buffer);
+ assertTrue(success, "Put returned false adding a unique key");
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(UnknownKeys, ccnxTlvDictionary_PutList_Duplicate)
+{
+ uint32_t listKey = FIXED_LIST_LENGTH + 1;
+ uint32_t bufferKey = 1000;
+
+ // its ok to have duplicates of the custom keys
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, bufferKey, buffer);
+ bool success = ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, bufferKey, buffer);
+ assertTrue(success, "Put returned false adding a duplicate key to list");
+ parcBuffer_Release(&buffer);
+}
+
+/*
+ * Add 3 items to list then make sure we can retrieve the 2nd
+ */
+LONGBOW_TEST_CASE(UnknownKeys, ccnxTlvDictionary_ListGetByPosition)
+{
+ uint32_t listKey = SchemaEnd;
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *a = parcBuffer_Allocate(1);
+ PARCBuffer *b = parcBuffer_Allocate(1);
+ PARCBuffer *c = parcBuffer_Allocate(1);
+
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1000, a);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1001, b);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1002, c);
+
+ PARCBuffer *test = NULL;
+ uint32_t testkey = 0;
+ ccnxTlvDictionary_ListGetByPosition(data->dictionary, listKey, 1, &test, &testkey);
+
+ assertTrue(testkey == 1001, "Wrong key, expected %u got %u", 1001, testkey);
+ assertTrue(test == b, "Wrong buffer, expected %p got %p", (void *) b, (void *) test);
+
+ parcBuffer_Release(&a);
+ parcBuffer_Release(&b);
+ parcBuffer_Release(&c);
+}
+
+/*
+ * Add 3 items to list then make sure we can retrieve the 2nd
+ */
+LONGBOW_TEST_CASE(UnknownKeys, ccnxTlvDictionary_ListGetByType)
+{
+ uint32_t listKey = SchemaEnd;
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *a = parcBuffer_Allocate(1);
+ PARCBuffer *b = parcBuffer_Allocate(1);
+ PARCBuffer *c = parcBuffer_Allocate(1);
+
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1000, a);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1001, b);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1002, c);
+
+ PARCBuffer *test = ccnxTlvDictionary_ListGetByType(data->dictionary, listKey, 1001);
+ assertTrue(test == b, "Wrong buffer, expected %p got %p", (void *) b, (void *) test);
+
+ parcBuffer_Release(&a);
+ parcBuffer_Release(&b);
+ parcBuffer_Release(&c);
+}
+
+LONGBOW_TEST_CASE(UnknownKeys, ccnxTlvDictionary_ListSize)
+{
+ uint32_t listKey = SchemaEnd;
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *a = parcBuffer_Allocate(1);
+ PARCBuffer *b = parcBuffer_Allocate(1);
+ PARCBuffer *c = parcBuffer_Allocate(1);
+
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1000, a);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1001, b);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, listKey, 1002, c);
+
+ size_t length = ccnxTlvDictionary_ListSize(data->dictionary, listKey);
+ assertTrue(length == 3, "Wrong length, expected %u got %zu", 3, length);
+
+ parcBuffer_Release(&a);
+ parcBuffer_Release(&b);
+ parcBuffer_Release(&c);
+}
+
+LONGBOW_TEST_CASE(UnknownKeys, ccnxTlvDictionary_ListEquals)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *a = parcBuffer_Allocate(1);
+ PARCBuffer *b = parcBuffer_Allocate(1);
+ PARCBuffer *c = parcBuffer_Allocate(1);
+
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, 6, 1000, a);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, 6, 1001, b);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, 6, 1002, c);
+
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, 7, 1000, a);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, 7, 1001, b);
+ ccnxTlvDictionary_PutListBuffer(data->dictionary, 7, 1002, c);
+
+ bool equals = _ccnxTlvDictionary_ListEquals(_getListHead(data->dictionary, 6), _getListHead(data->dictionary, 7));
+ assertTrue(equals, "Lists should be equal");
+
+ parcBuffer_Release(&a);
+ parcBuffer_Release(&b);
+ parcBuffer_Release(&c);
+}
+
+
+
+// =============================================================
+
+LONGBOW_TEST_FIXTURE(Buffer)
+{
+ LONGBOW_RUN_TEST_CASE(Buffer, ccnxTlvDictionary_GetBuffer_Exists);
+ LONGBOW_RUN_TEST_CASE(Buffer, ccnxTlvDictionary_GetBuffer_Missing);
+ LONGBOW_RUN_TEST_CASE(Buffer, ccnxTlvDictionary_PutBuffer_OK);
+ LONGBOW_RUN_TEST_CASE(Buffer, ccnxTlvDictionary_PutBuffer_Duplicate);
+ LONGBOW_RUN_TEST_CASE(Buffer, ccnxTlvDictionary_IsValueBuffer_True);
+ LONGBOW_RUN_TEST_CASE(Buffer, ccnxTlvDictionary_IsValueBuffer_False);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Buffer)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Buffer)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Buffer, ccnxTlvDictionary_GetBuffer_Exists)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(data->dictionary, SchemaBuffer);
+ assertNotNull(test, "Got null buffer from key that hsould be buffer");
+}
+
+LONGBOW_TEST_CASE(Buffer, ccnxTlvDictionary_GetBuffer_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxTlvDictionary_GetBuffer(data->dictionary, SchemaFree);
+}
+
+LONGBOW_TEST_CASE(Buffer, ccnxTlvDictionary_PutBuffer_OK)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ bool success = ccnxTlvDictionary_PutBuffer(data->dictionary, SchemaFree, buffer);
+ assertTrue(success, "Did not put buffer in to available slot");
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Buffer, ccnxTlvDictionary_PutBuffer_Duplicate)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ bool success = ccnxTlvDictionary_PutBuffer(data->dictionary, SchemaBuffer, buffer);
+ assertFalse(success, "Should have failed putting duplicate");
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Buffer, ccnxTlvDictionary_IsValueBuffer_True)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueBuffer(data->dictionary, SchemaBuffer);
+ assertTrue(success, "Should have succeeded on a buffer key");
+}
+
+LONGBOW_TEST_CASE(Buffer, ccnxTlvDictionary_IsValueBuffer_False)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueBuffer(data->dictionary, SchemaInteger);
+ assertFalse(success, "Should have failed on a non-buffer");
+}
+
+// =============================================================
+
+LONGBOW_TEST_FIXTURE(Integer)
+{
+ LONGBOW_RUN_TEST_CASE(Integer, ccnxTlvDictionary_GetInteger_Exists);
+ LONGBOW_RUN_TEST_CASE(Integer, ccnxTlvDictionary_GetInteger_Missing);
+ LONGBOW_RUN_TEST_CASE(Integer, ccnxTlvDictionary_PutInteger_OK);
+ LONGBOW_RUN_TEST_CASE(Integer, ccnxTlvDictionary_PutInteger_Duplicate);
+ LONGBOW_RUN_TEST_CASE(Integer, ccnxTlvDictionary_PutInteger_OverBuffer);
+ LONGBOW_RUN_TEST_CASE(Integer, ccnxTlvDictionary_IsValueInteger_True);
+ LONGBOW_RUN_TEST_CASE(Integer, ccnxTlvDictionary_IsValueInteger_False);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Integer)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Integer)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Integer, ccnxTlvDictionary_GetInteger_Exists)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint64_t test = ccnxTlvDictionary_GetInteger(data->dictionary, SchemaInteger);
+ assertTrue(test == 42, "Got wrong integer, got %" PRIu64 " expected 42", test);
+}
+
+LONGBOW_TEST_CASE_EXPECTS(Integer, ccnxTlvDictionary_GetInteger_Missing, .event = &LongBowTrapIllegalValue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxTlvDictionary_GetInteger(data->dictionary, SchemaBuffer);
+}
+
+LONGBOW_TEST_CASE(Integer, ccnxTlvDictionary_PutInteger_OK)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_PutInteger(data->dictionary, SchemaFree, 69);
+ assertTrue(success, "Did not put integer in to available slot");
+}
+
+LONGBOW_TEST_CASE(Integer, ccnxTlvDictionary_PutInteger_Duplicate)
+{
+ // we allow replacing integer
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_PutInteger(data->dictionary, SchemaInteger, 69);
+ assertTrue(success, "Should have succeeded putting duplicate");
+}
+
+LONGBOW_TEST_CASE(Integer, ccnxTlvDictionary_PutInteger_OverBuffer)
+{
+ // This will fail, cannot change a buffer to an integer
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_PutInteger(data->dictionary, SchemaBuffer, 69);
+ assertFalse(success, "Should not be able to change a buffer to an integer");
+}
+
+LONGBOW_TEST_CASE(Integer, ccnxTlvDictionary_IsValueInteger_True)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueInteger(data->dictionary, SchemaInteger);
+ assertTrue(success, "Should have succeeded on a integer key");
+}
+
+LONGBOW_TEST_CASE(Integer, ccnxTlvDictionary_IsValueInteger_False)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueInteger(data->dictionary, SchemaBuffer);
+ assertFalse(success, "Should have failed on a non-integer");
+}
+
+// =============================================================
+
+LONGBOW_TEST_FIXTURE(IoVec)
+{
+ LONGBOW_RUN_TEST_CASE(IoVec, ccnxTlvDictionary_GetIoVec_Exists);
+ LONGBOW_RUN_TEST_CASE(IoVec, ccnxTlvDictionary_GetIoVec_Missing);
+ LONGBOW_RUN_TEST_CASE(IoVec, ccnxTlvDictionary_PutIoVec_OK);
+ LONGBOW_RUN_TEST_CASE(IoVec, ccnxTlvDictionary_PutIoVec_Duplicate);
+ LONGBOW_RUN_TEST_CASE(IoVec, ccnxTlvDictionary_IsValueIoVec_True);
+ LONGBOW_RUN_TEST_CASE(IoVec, ccnxTlvDictionary_IsValueIoVec_False);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(IoVec)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(IoVec)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(IoVec, ccnxTlvDictionary_GetIoVec_Exists)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxCodecNetworkBufferIoVec *test = ccnxTlvDictionary_GetIoVec(data->dictionary, SchemaIoVec);
+ assertNotNull(test, "Got null buffer from key that hsould be buffer");
+}
+
+LONGBOW_TEST_CASE(IoVec, ccnxTlvDictionary_GetIoVec_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxTlvDictionary_GetIoVec(data->dictionary, SchemaFree);
+}
+
+LONGBOW_TEST_CASE(IoVec, ccnxTlvDictionary_PutIoVec_OK)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxCodecNetworkBufferIoVec *vec = createIoVec();
+ bool success = ccnxTlvDictionary_PutIoVec(data->dictionary, SchemaFree, vec);
+ assertTrue(success, "Did not put vec in to available slot");
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+LONGBOW_TEST_CASE(IoVec, ccnxTlvDictionary_PutIoVec_Duplicate)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxCodecNetworkBufferIoVec *vec = createIoVec();
+ bool success = ccnxTlvDictionary_PutIoVec(data->dictionary, SchemaIoVec, vec);
+ assertFalse(success, "Should have failed putting duplicate");
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+LONGBOW_TEST_CASE(IoVec, ccnxTlvDictionary_IsValueIoVec_True)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueIoVec(data->dictionary, SchemaIoVec);
+ assertTrue(success, "Should have succeeded on a vec key");
+}
+
+LONGBOW_TEST_CASE(IoVec, ccnxTlvDictionary_IsValueIoVec_False)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueIoVec(data->dictionary, SchemaInteger);
+ assertFalse(success, "Should have failed on a non-vec");
+}
+
+// =============================================================
+
+LONGBOW_TEST_FIXTURE(Json)
+{
+ LONGBOW_RUN_TEST_CASE(Json, ccnxTlvDictionary_GetJson_Exists);
+ LONGBOW_RUN_TEST_CASE(Json, ccnxTlvDictionary_GetJson_Missing);
+ LONGBOW_RUN_TEST_CASE(Json, ccnxTlvDictionary_PutJson_OK);
+ LONGBOW_RUN_TEST_CASE(Json, ccnxTlvDictionary_PutJson_Duplicate);
+ LONGBOW_RUN_TEST_CASE(Json, ccnxTlvDictionary_IsValueJson_True);
+ LONGBOW_RUN_TEST_CASE(Json, ccnxTlvDictionary_IsValueJson_False);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Json)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Json)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Json, ccnxTlvDictionary_GetJson_Exists)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCJSON *test = ccnxTlvDictionary_GetJson(data->dictionary, SchemaJson);
+ assertNotNull(test, "Got null json from key that should be json");
+}
+
+LONGBOW_TEST_CASE(Json, ccnxTlvDictionary_GetJson_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCJSON *test = ccnxTlvDictionary_GetJson(data->dictionary, SchemaFree);
+ assertNull(test, "Should have gotten null for non-json key");
+}
+
+LONGBOW_TEST_CASE(Json, ccnxTlvDictionary_PutJson_OK)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCJSON *json = parcJSON_Create();
+ bool success = ccnxTlvDictionary_PutJson(data->dictionary, SchemaFree, json);
+ assertTrue(success, "Did not put buffer in to available slot");
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(Json, ccnxTlvDictionary_PutJson_Duplicate)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCJSON *json = parcJSON_Create();
+ bool success = ccnxTlvDictionary_PutJson(data->dictionary, SchemaJson, json);
+ assertFalse(success, "Should have failed putting duplicate");
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(Json, ccnxTlvDictionary_IsValueJson_True)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueJson(data->dictionary, SchemaJson);
+ assertTrue(success, "Should have succeeded on a json key");
+}
+
+LONGBOW_TEST_CASE(Json, ccnxTlvDictionary_IsValueJson_False)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueJson(data->dictionary, SchemaInteger);
+ assertFalse(success, "Should have failed on a non-json");
+}
+
+// =============================================================
+
+LONGBOW_TEST_FIXTURE(Name)
+{
+ LONGBOW_RUN_TEST_CASE(Name, ccnxTlvDictionary_GetName_Exists);
+ LONGBOW_RUN_TEST_CASE(Name, ccnxTlvDictionary_GetName_Missing);
+ LONGBOW_RUN_TEST_CASE(Name, ccnxTlvDictionary_PutName_OK);
+ LONGBOW_RUN_TEST_CASE(Name, ccnxTlvDictionary_PutName_Duplicate);
+ LONGBOW_RUN_TEST_CASE(Name, ccnxTlvDictionary_IsValueName_True);
+ LONGBOW_RUN_TEST_CASE(Name, ccnxTlvDictionary_IsValueName_False);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Name)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Name)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Name, ccnxTlvDictionary_GetName_Exists)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxName *test = ccnxTlvDictionary_GetName(data->dictionary, SchemaName);
+ assertNotNull(test, "Got null json from key that should be name");
+}
+
+LONGBOW_TEST_CASE(Name, ccnxTlvDictionary_GetName_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxName *test = ccnxTlvDictionary_GetName(data->dictionary, SchemaFree);
+ assertNull(test, "Should have gotten null for non-name key");
+}
+
+LONGBOW_TEST_CASE(Name, ccnxTlvDictionary_PutName_OK)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxName *name = ccnxName_Create();
+ bool success = ccnxTlvDictionary_PutName(data->dictionary, SchemaFree, name);
+ assertTrue(success, "Did not put name in to available slot");
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(Name, ccnxTlvDictionary_PutName_Duplicate)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxName *name = ccnxName_Create();
+ bool success = ccnxTlvDictionary_PutName(data->dictionary, SchemaName, name);
+ assertFalse(success, "Should have failed putting duplicate");
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(Name, ccnxTlvDictionary_IsValueName_True)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueName(data->dictionary, SchemaName);
+ assertTrue(success, "Should have succeeded on a json key");
+}
+
+LONGBOW_TEST_CASE(Name, ccnxTlvDictionary_IsValueName_False)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool success = ccnxTlvDictionary_IsValueName(data->dictionary, SchemaInteger);
+ assertFalse(success, "Should have failed on a non-json");
+}
+
+// =============================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _rtaTlvEntry_Equals_Unset);
+ LONGBOW_RUN_TEST_CASE(Local, _rtaTlvEntry_Equals_Buffer);
+ LONGBOW_RUN_TEST_CASE(Local, _rtaTlvEntry_Equals_Integer);
+ LONGBOW_RUN_TEST_CASE(Local, _rtaTlvEntry_Equals_IoVec);
+ LONGBOW_RUN_TEST_CASE(Local, _rtaTlvEntry_Equals_Json);
+ LONGBOW_RUN_TEST_CASE(Local, _rtaTlvEntry_Equals_Name);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+static void
+assertRtaTlvEntryEquals(int length, _CCNxTlvDictionaryEntry array[length])
+{
+ assertTrue(length == 5, "Must provide 5 array elements");
+ assertEqualsContract((bool (*)(void *, void *))_ccnxTlvDictionaryEntry_Equals, &array[0], &array[1], &array[2], &array[3], &array[4], NULL);
+}
+
+LONGBOW_TEST_CASE(Local, _rtaTlvEntry_Equals_Unset)
+{
+ _CCNxTlvDictionaryEntry array[5];
+ memset(&array, 0, sizeof(array));
+
+ array[3].entryType = ENTRY_JSON;
+ array[4].entryType = ENTRY_BUFFER;
+ assertRtaTlvEntryEquals(5, array);
+}
+
+LONGBOW_TEST_CASE(Local, _rtaTlvEntry_Equals_Buffer)
+{
+ char apple[] = "apple";
+ char bananna[] = "bannana";
+
+ _CCNxTlvDictionaryEntry array[5];
+ memset(&array, 0, sizeof(array));
+
+ for (int i = 0; i < 3; i++) {
+ array[i].entryType = ENTRY_BUFFER;
+ array[i]._entry.buffer = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(20), sizeof(apple), (uint8_t *) apple));
+ }
+
+ array[3].entryType = ENTRY_JSON;
+ array[4].entryType = ENTRY_BUFFER;
+ array[4]._entry.buffer = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(20), sizeof(bananna), (uint8_t *) bananna));
+ assertRtaTlvEntryEquals(5, array);
+
+ for (int i = 0; i < 5; i++) {
+ if (array[i]._entry.buffer) {
+ parcBuffer_Release(&array[i]._entry.buffer);
+ }
+ }
+}
+
+LONGBOW_TEST_CASE(Local, _rtaTlvEntry_Equals_Integer)
+{
+ _CCNxTlvDictionaryEntry array[5];
+ memset(&array, 0, sizeof(array));
+
+ for (int i = 0; i < 3; i++) {
+ array[i].entryType = ENTRY_INTEGER;
+ array[i]._entry.integer = 13;
+ }
+
+ array[3].entryType = ENTRY_JSON;
+ array[4].entryType = ENTRY_INTEGER;
+ array[4]._entry.integer = 99;
+
+ assertRtaTlvEntryEquals(5, array);
+}
+
+LONGBOW_TEST_CASE(Local, _rtaTlvEntry_Equals_IoVec)
+{
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL);
+ ccnxCodecNetworkBuffer_PutUint8(netbuff, 0);
+ CCNxCodecNetworkBufferIoVec *unequal = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+
+ _CCNxTlvDictionaryEntry array[5];
+ memset(&array, 0, sizeof(array));
+
+ for (int i = 0; i < 3; i++) {
+ array[i].entryType = ENTRY_IOVEC;
+ array[i]._entry.vec = createIoVec();
+ }
+
+ array[3].entryType = ENTRY_JSON;
+ array[4].entryType = ENTRY_IOVEC;
+ array[4]._entry.vec = unequal;
+ assertRtaTlvEntryEquals(5, array);
+
+ for (int i = 0; i < 5; i++) {
+ if (array[i]._entry.vec) {
+ ccnxCodecNetworkBufferIoVec_Release(&array[i]._entry.vec);
+ }
+ }
+}
+
+LONGBOW_TEST_CASE(Local, _rtaTlvEntry_Equals_Json)
+{
+ char apple[] = "{\"apple\": 0}";
+ char bananna[] = "{\"bannana\": 1}";
+
+ _CCNxTlvDictionaryEntry array[5];
+ memset(&array, 0, sizeof(array));
+
+ for (int i = 0; i < 3; i++) {
+ array[i].entryType = ENTRY_JSON;
+ array[i]._entry.json = parcJSON_ParseString(apple);
+ }
+
+ array[3].entryType = ENTRY_JSON;
+ array[4].entryType = ENTRY_JSON;
+ array[4]._entry.json = parcJSON_ParseString(bananna);
+ assertRtaTlvEntryEquals(5, array);
+
+ for (int i = 0; i < 5; i++) {
+ if (array[i]._entry.json) {
+ parcJSON_Release(&array[i]._entry.json);
+ }
+ }
+}
+
+LONGBOW_TEST_CASE(Local, _rtaTlvEntry_Equals_Name)
+{
+ char apple[] = "lci:/apple";
+ char bananna[] = "lci:/bannana";
+
+ _CCNxTlvDictionaryEntry array[5];
+ memset(&array, 0, sizeof(array));
+
+ for (int i = 0; i < 3; i++) {
+ array[i].entryType = ENTRY_NAME;
+ array[i]._entry.name = ccnxName_CreateFromCString(apple);
+ }
+
+ array[3].entryType = ENTRY_JSON;
+ array[4].entryType = ENTRY_NAME;
+ array[4]._entry.name = ccnxName_CreateFromCString(bananna);
+ assertRtaTlvEntryEquals(5, array);
+
+ for (int i = 0; i < 5; i++) {
+ if (array[i]._entry.name) {
+ ccnxName_Release(&array[i]._entry.name);
+ }
+ }
+}
+
+// =============================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_TlvDictionary);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ValidationFacade b/libccnx-common/ccnx/common/internal/test/test_ccnx_ValidationFacade
new file mode 100755
index 00000000..39a27830
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ValidationFacade
Binary files differ
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_ValidationFacadeV1.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_ValidationFacadeV1.c
new file mode 100755
index 00000000..fe3ead29
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_ValidationFacadeV1.c
@@ -0,0 +1,444 @@
+/*
+ * 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.
+ */
+
+/**
+ * Setter tests use ground truth by examining the dictionary.
+ * Getter tests use the setters to set values.
+ *
+ */
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_ValidationFacadeV1.c"
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+
+//#include "../validation/test/testrig_validation.c"
+
+LONGBOW_TEST_RUNNER(ccnx_ValidationFacadeV1)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Setters);
+ LONGBOW_RUN_TEST_FIXTURE(Getters);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_ValidationFacadeV1)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_ValidationFacadeV1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Setters)
+{
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_SetKeyId);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_SetKeyName);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_SetPublicKey);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_SetCertificate);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_SetPayload);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_SetCryptoSuite);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_SetSigningTime);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Setters)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Setters)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_SetKeyId)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *keyid = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ bool success = ccnxValidationFacadeV1_SetKeyId(dictionary, keyid);
+ assertTrue(success, "Failed to set keyid");
+
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID);
+ assertTrue(parcBuffer_Equals(test, keyid), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(keyid, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&keyid);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_SetKeyName)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *keyid = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ PARCBuffer *hash = parcBuffer_Wrap((uint8_t []) { 11, 12, 13, 14 }, 4, 0, 4);
+ CCNxName *name = ccnxName_CreateFromCString("lci:/foo");
+ CCNxLink *link = ccnxLink_Create(name, keyid, hash);
+
+ bool success = ccnxValidationFacadeV1_SetKeyName(dictionary, link);
+ assertTrue(success, "Failed to set keyname");
+
+ CCNxName *testName = ccnxTlvDictionary_GetName(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME);
+ assertTrue(ccnxName_Equals(testName, name), "Wrong name")
+ {
+ printf("Expected\n");
+ ccnxName_Display(name, 3);
+ printf("Got\n");
+ ccnxName_Display(testName, 3);
+ }
+
+ PARCBuffer *testKeyid = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_KEYID);
+ assertTrue(parcBuffer_Equals(testKeyid, keyid), "Wrong keyid")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(keyid, 3);
+ printf("Got\n");
+ parcBuffer_Display(testKeyid, 3);
+ }
+
+ PARCBuffer *testHash = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_OBJHASH);
+ assertTrue(parcBuffer_Equals(testHash, hash), "Wrong hash")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(hash, 3);
+ printf("Got\n");
+ parcBuffer_Display(testHash, 3);
+ }
+
+ parcBuffer_Release(&hash);
+ parcBuffer_Release(&keyid);
+ ccnxName_Release(&name);
+ ccnxLink_Release(&link);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_SetPublicKey)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *key = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ bool success = ccnxValidationFacadeV1_SetPublicKey(dictionary, key);
+ assertTrue(success, "Failed to set keyid");
+
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY);
+ assertTrue(parcBuffer_Equals(test, key), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(key, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&key);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_SetCertificate)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *cert = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ bool success = ccnxValidationFacadeV1_SetCertificate(dictionary, cert);
+ assertTrue(success, "Failed to set keyid");
+
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CERT);
+ assertTrue(parcBuffer_Equals(test, cert), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(cert, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&cert);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_SetPayload)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *payload = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ bool success = ccnxValidationFacadeV1_SetPayload(dictionary, payload);
+ assertTrue(success, "Failed to set keyid");
+
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+ assertTrue(parcBuffer_Equals(test, payload), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(payload, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&payload);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_SetCryptoSuite)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCCryptoSuite suite = PARCCryptoSuite_RSA_SHA256;
+ bool success = ccnxValidationFacadeV1_SetCryptoSuite(dictionary, suite);
+ assertTrue(success, "Failed to set keyid");
+
+ bool hasCryptoSuite = ccnxTlvDictionary_IsValueInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE);
+ assertTrue(hasCryptoSuite, "Dictionary does not have a crypto suite value in it");
+
+ PARCCryptoSuite test = (PARCCryptoSuite) ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE);
+ assertTrue(test == suite, "Wrong suite, expected %d got %d", suite, test);
+
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_SetSigningTime)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ uint64_t signingTime = 0x0102030405060708ULL;
+
+ bool success = ccnxValidationFacadeV1_SetSigningTime(dictionary, signingTime);
+ assertTrue(success, "Failed to set signing time");
+
+ bool hasSigningTime = ccnxTlvDictionary_IsValueInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME);
+ assertTrue(hasSigningTime, "Dictionary does not have a signing time value in it");
+
+ uint64_t test = ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME);
+ assertTrue(test == signingTime, "Wrong signing time, expected %" PRIx64 " got %" PRIx64, signingTime, test);
+
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+// =============================================================
+
+LONGBOW_TEST_FIXTURE(Getters)
+{
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_GetKeyId);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_GetKeyName);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_GetPublicKey);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_GetCertificate);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_GetPayload);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_HasCryptoSuite_True);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_HasCryptoSuite_False);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_GetCryptoSuite);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_HasSigningTime_True);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_HasSigningTime_False);
+ LONGBOW_RUN_TEST_CASE(Setters, ccnxValidationFacadeV1_GetSigningTime);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Getters)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Getters)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_GetKeyId)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *keyid = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ ccnxValidationFacadeV1_SetKeyId(dictionary, keyid);
+
+ PARCBuffer *test = ccnxValidationFacadeV1_GetKeyId(dictionary);
+ assertTrue(parcBuffer_Equals(test, keyid), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(keyid, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&keyid);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_GetKeyName)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *keyid = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ PARCBuffer *hash = parcBuffer_Wrap((uint8_t []) { 11, 12, 13, 14 }, 4, 0, 4);
+ CCNxName *name = ccnxName_CreateFromCString("lci:/foo");
+ CCNxLink *link = ccnxLink_Create(name, keyid, hash);
+
+ ccnxValidationFacadeV1_SetKeyName(dictionary, link);
+
+ CCNxLink *testLink = ccnxValidationFacadeV1_GetKeyName(dictionary);
+ assertTrue(ccnxLink_Equals(testLink, link), "Wrong link");
+ // no ccnxLink_Dispay, so cannot easily display items
+
+ ccnxLink_Release(&testLink);
+ parcBuffer_Release(&hash);
+ parcBuffer_Release(&keyid);
+ ccnxName_Release(&name);
+ ccnxLink_Release(&link);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_GetPublicKey)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *key = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ ccnxValidationFacadeV1_SetPublicKey(dictionary, key);
+
+ PARCBuffer *test = ccnxValidationFacadeV1_GetPublicKey(dictionary);
+ assertTrue(parcBuffer_Equals(test, key), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(key, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&key);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_GetCertificate)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *cert = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ ccnxValidationFacadeV1_SetCertificate(dictionary, cert);
+
+ PARCBuffer *test = ccnxValidationFacadeV1_GetCertificate(dictionary);
+ assertTrue(parcBuffer_Equals(test, cert), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(cert, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&cert);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_GetPayload)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCBuffer *payload = parcBuffer_Wrap((uint8_t []) { 1, 2, 3, 4, 5 }, 5, 0, 5);
+ ccnxValidationFacadeV1_SetPayload(dictionary, payload);
+
+ PARCBuffer *test = ccnxValidationFacadeV1_GetPayload(dictionary);
+ assertTrue(parcBuffer_Equals(test, payload), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(payload, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&payload);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_HasCryptoSuite_True)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCCryptoSuite suite = PARCCryptoSuite_RSA_SHA256;
+ ccnxValidationFacadeV1_SetCryptoSuite(dictionary, suite);
+
+ bool hasCryptoSuite = ccnxValidationFacadeV1_HasCryptoSuite(dictionary);
+ assertTrue(hasCryptoSuite, "Dictionary does not have a crypto suite value in it");
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_HasCryptoSuite_False)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ bool hasCryptoSuite = ccnxValidationFacadeV1_HasCryptoSuite(dictionary);
+ assertFalse(hasCryptoSuite, "Dictionary says it has a crypto suite when none was set");
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_GetCryptoSuite)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ PARCCryptoSuite suite = PARCCryptoSuite_RSA_SHA256;
+ ccnxValidationFacadeV1_SetCryptoSuite(dictionary, suite);
+
+ PARCCryptoSuite test = ccnxValidationFacadeV1_GetCryptoSuite(dictionary);
+ assertTrue(test == suite, "Wrong crypto suite, expected %d got %d", suite, test);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_HasSigningTime_True)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ uint64_t signingTime = 0x0102030405060708ULL;
+ ccnxValidationFacadeV1_SetSigningTime(dictionary, signingTime);
+
+ bool hasSigningTime = ccnxValidationFacadeV1_HasSigningTime(dictionary);
+ assertTrue(hasSigningTime, "Dictionary does not have a signing time value in it");
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_HasSigningTime_False)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ bool hasSigningTime = ccnxValidationFacadeV1_HasSigningTime(dictionary);
+ assertFalse(hasSigningTime, "Dictionary says it has a signing time when none was set");
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Setters, ccnxValidationFacadeV1_GetSigningTime)
+{
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ uint64_t signingTime = 0x0102030405060708ULL;
+ ccnxValidationFacadeV1_SetSigningTime(dictionary, signingTime);
+
+ uint64_t test = ccnxValidationFacadeV1_GetSigningTime(dictionary);
+ assertTrue(test == signingTime, "Wrong signing time, expected %" PRIx64 " got %" PRIx64, signingTime, test);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+
+// =============================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_ValidationFacadeV1);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c
new file mode 100755
index 00000000..194ef02c
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c
@@ -0,0 +1,594 @@
+/*
+ * 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 the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnx_WireFormatFacadeV1.c"
+
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/ccnx_ContentObject.h>
+#include <ccnx/common/ccnx_WireFormatMessage.h>
+#include <ccnx/common/codec/ccnxCodec_TlvPacket.h>
+
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_nameA.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_crc32c.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route.h>
+
+LONGBOW_TEST_RUNNER(ccnx_WireFormatFacade)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(SchemaV1);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_WireFormatFacade)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_WireFormatFacade)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+/*
+ * Small size allocator for creating a network buffer
+ */
+static size_t
+allocator(void *userarg, size_t bytes, void **output)
+{
+ const size_t allocationSize = *(size_t *) userarg;
+ void *allocated = parcMemory_Allocate(allocationSize);
+ *output = allocated;
+ return allocationSize;
+}
+
+/*
+ * deallocator for network buffer
+ */
+static void
+deallocator(void *userarg, void **memoryPtr)
+{
+ parcMemory_Deallocate(memoryPtr);
+}
+
+static const CCNxCodecNetworkBufferMemoryBlockFunctions memory = { .allocator = allocator, .deallocator = deallocator };
+
+/*
+ * Create a network buffer that looks like this. The actual number of iovecs might
+ * be a little different, but the digest area will span several iovec.
+ *
+ * +-----------+-----------+-----------+-----------+-----------+
+ * iov[0] iov[1] iov[2] iov[3]
+ * +-----------+-----------+-----------+-----------+-----------+
+ * ^ ^
+ * | |
+ * start end
+ */
+static CCNxCodecNetworkBufferIoVec *
+createNetworkBufferIoVec(size_t allocationSize, size_t padlen, uint8_t pad[padlen], size_t datalen, uint8_t data[datalen])
+{
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_Create(&memory, &allocationSize);
+ // build the network buffer
+ ccnxCodecNetworkBuffer_PutArray(netbuff, padlen, pad);
+ ccnxCodecNetworkBuffer_PutArray(netbuff, datalen, data);
+ ccnxCodecNetworkBuffer_PutArray(netbuff, padlen, pad);
+
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+ return vec;
+}
+
+// =======================================================================
+
+LONGBOW_TEST_FIXTURE(SchemaV1)
+{
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromContentObjectPacketType);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromControlPacketType);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestPacketType);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestReturnPacketType);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Get);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Put);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_WriteToFile);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestPacketTypeIoVec);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_GetIoVec);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetHopLimit);
+
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetProtectedRegionStart);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetProtectedRegionLength);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_HashProtectedRegion_Buffer);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_HashProtectedRegion_IoVec);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_ComputeContentObjectHash);
+
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_Interest);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_ContentObject);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_Control);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_InterestReturn);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_UnknownPacketType);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(SchemaV1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(SchemaV1)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromContentObjectPacketType)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromContentObjectPacketType(buffer);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsContentObject(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromControlPacketType)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromControlPacketType(buffer);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsControl(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestPacketType)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestPacketType(buffer);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsInterest(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestReturnPacketType)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestReturnPacketType(buffer);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsInterestReturn(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Get)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestPacketType(buffer);
+
+ PARCBuffer *test = _ccnxWireFormatFacadeV1_GetWireFormatBuffer(wireformat);
+ assertTrue(test == buffer, "Wrong iovec: got %p expected %p", (void *) test, (void *) buffer);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Put)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *packet = ccnxTlvDictionary_Create(20, 20);
+ ccnxTlvDictionary_SetMessageType_Interest(packet, CCNxTlvDictionary_SchemaVersion_V1);
+ bool success = _ccnxWireFormatFacadeV1_PutWireFormatBuffer(packet, buffer);
+
+ assertTrue(success, "Failed to put buffer in to dictionary");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_WriteToFile)
+{
+ const char string[] = "Hello dev null\n";
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestPacketType(buffer);
+
+ _ccnxWireFormatFacadeV1_WriteToFile(wireformat, "/dev/null");
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestPacketTypeIoVec)
+{
+ uint8_t data[64];
+
+ uint8_t pad[32];
+ CCNxCodecNetworkBufferIoVec *vec = createNetworkBufferIoVec(512, 32, pad, 64, data);
+
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestPacketTypeIoVec(vec);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsInterest(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_GetIoVec)
+{
+ uint8_t *data = parcMemory_Allocate(64);
+ memset(data, 0, 64);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_CreateFromArray(&ParcMemoryMemoryBlock, NULL, 64, data);
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutIoVec(packet, iovec);
+
+ CCNxCodecNetworkBufferIoVec *test = _ccnxWireFormatFacadeV1_GetIoVec(packet);
+ assertTrue(test == iovec, "Failed to get iovec from dictionary, expected %p got %p", (void *) iovec, (void *) test);
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetHopLimit)
+{
+ uint8_t *data = parcMemory_Allocate(64);
+ memset(data, 0, 64);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_CreateFromArray(&ParcMemoryMemoryBlock, NULL, 64, data);
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutIoVec(packet, iovec);
+
+ _ccnxWireFormatFacadeV1_SetHopLimit(packet, 10);
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+
+ CCNxCodecSchemaV1InterestHeader header;
+
+ buffer = parcBuffer_Wrap((void *) &header, sizeof(header), 0, sizeof(header));
+
+ packet = _ccnxWireFormatFacadeV1_FromContentObjectPacketType(buffer);
+
+ _ccnxWireFormatFacadeV1_SetHopLimit(packet, 10);
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetProtectedRegionStart)
+{
+ const char string[] = "Hello dev null\n";
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutWireFormatBuffer(packet, buffer);
+
+ size_t start = 5;
+ bool success = _ccnxWireFormatFacadeV1_SetProtectedRegionStart(packet, start);
+ assertTrue(success, "Failed to put integer in to dictionary");
+
+ assertTrue(ccnxTlvDictionary_IsValueInteger(packet, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedStart), "ProtectedStart not set");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetProtectedRegionLength)
+{
+ const char string[] = "Hello dev null\n";
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutWireFormatBuffer(packet, buffer);
+
+ size_t length = 5;
+ bool success = _ccnxWireFormatFacadeV1_SetProtectedRegionLength(packet, length);
+ assertTrue(success, "Failed to put integer in to dictionary");
+
+ assertTrue(ccnxTlvDictionary_IsValueInteger(packet, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedLength), "ProtectedLength not set");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_HashProtectedRegion_Buffer)
+{
+ // >1234<
+ const char string[] = "Hello dev null\n";
+
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+ size_t start = 5;
+ size_t length = 4;
+
+ CCNxTlvDictionary *packet = _ccnxWireFormatFacadeV1_FromContentObjectPacketType(buffer);
+ _ccnxWireFormatFacadeV1_SetProtectedRegionStart(packet, start);
+ _ccnxWireFormatFacadeV1_SetProtectedRegionLength(packet, length);
+
+ PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
+ PARCCryptoHash *hash = _ccnxWireFormatFacadeV1_HashProtectedRegion(packet, hasher);
+
+ // the correctness of the has is tested in _ccnxWireFormatFacadeV1_ComputeHash
+ assertNotNull(hash, "Got null hash from a good packet");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcCryptoHash_Release(&hash);
+ parcBuffer_Release(&buffer);
+ parcCryptoHasher_Release(&hasher);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_HashProtectedRegion_IoVec)
+{
+ uint8_t *data = parcMemory_Allocate(64);
+ memset(data, 0, 64);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_CreateFromArray(&ParcMemoryMemoryBlock, NULL, 64, data);
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutIoVec(packet, iovec);
+
+ _ccnxWireFormatFacadeV1_SetProtectedRegionStart(packet, 0);
+ _ccnxWireFormatFacadeV1_SetProtectedRegionLength(packet, 64);
+
+ PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
+ PARCCryptoHash *hash = _ccnxWireFormatFacadeV1_HashProtectedRegion(packet, hasher);
+
+ // the correctness of the has is tested in _ccnxWireFormatFacadeV1_ComputeHash
+ assertNotNull(hash, "Got null hash from a good packet");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcCryptoHash_Release(&hash);
+ parcBuffer_Release(&buffer);
+ parcCryptoHasher_Release(&hasher);
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_Interest)
+{
+ PARCBuffer *wireFormat = parcBuffer_Wrap(v1_interest_nameA, sizeof(v1_interest_nameA), 0, sizeof(v1_interest_nameA));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNotNull(test, "Got null dictionary for good interest");
+ assertTrue(ccnxTlvDictionary_IsInterest(test), "Dictionary says it is not an Interest");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == 1, "Schema says it is not v1");
+ parcBuffer_Release(&wireFormat);
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_ContentObject)
+{
+ PARCBuffer *wireFormat = parcBuffer_Wrap(v1_content_nameA_crc32c, sizeof(v1_content_nameA_crc32c), 0, sizeof(v1_content_nameA_crc32c));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNotNull(test, "Got null dictionary for good content object");
+ assertTrue(ccnxTlvDictionary_IsContentObject(test), "Dictionary says it is not a Content Object");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == 1, "Schema says it is not v1");
+ parcBuffer_Release(&wireFormat);
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_Control)
+{
+ PARCBuffer *wireFormat = parcBuffer_Wrap(v1_cpi_add_route, sizeof(v1_cpi_add_route), 0, sizeof(v1_cpi_add_route));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNotNull(test, "Got null dictionary for good control");
+ assertTrue(ccnxTlvDictionary_IsControl(test), "Dictionary says it is not a control");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == 1, "Schema says it is not v1");
+ parcBuffer_Release(&wireFormat);
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_InterestReturn)
+{
+ uint8_t encoded[] = { 1, CCNxCodecSchemaV1Types_PacketType_InterestReturn, 0, 23 };
+ PARCBuffer *wireFormat = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNotNull(test, "Got null dictionary for good InterestReturn");
+ assertTrue(ccnxTlvDictionary_IsInterestReturn(test), "Expected IsInterestReturn() to be true");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == 1, "Schema says it is not v1");
+ parcBuffer_Release(&wireFormat);
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_UnknownPacketType)
+{
+ uint8_t encoded[] = { 1, 99, 0, 23 };
+ PARCBuffer *wireFormat = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNull(test, "Should have gotten null dictionary for unknown packet type");
+ parcBuffer_Release(&wireFormat);
+}
+
+
+static uint8_t _v1_ContentObject_WithKnownHash[] = {
+ // Name: lci:/boose/roo/pie
+ // Payload: "this is the payload"
+ // Signer: CRC32
+ // CO Hash: 4FB301EA5FD523B9A71287B721DC20C94B2D4827674A8CA275B7D57C60447876
+
+ 0x01, 0x01, 0x00, 0x4e, // Fixed Header
+ 0x00, 0x00, 0x00, 0x08,
+
+ 0x00, 0x02, 0x00, 0x32, // Type 2 == ContentObject, length 50 (0x32)
+ 0x00, 0x00, 0x00, 0x17, // Name, length 23 (0x17)
+
+ 0x00, 0x01, 0x00, 0x05, // NameSegment, length 5
+ 0x62, 0x6f, 0x6f, 0x73, // "boose"
+ 0x65,
+
+ 0x00, 0x01, 0x00, 0x03, // NameSegment, length 3
+ 0x72, 0x6f, 0x6f, // "roo"
+
+ 0x00, 0x01, 0x00, 0x03, // NameSegment, length 3
+ 0x70, 0x69, 0x65, // "pie"
+
+ 0x00, 0x01, 0x00, 0x13, // Payload, length 19 (0x13)
+ 0x74, 0x68, 0x69, 0x73, // "this is the payload"
+ 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x61, 0x79, 0x6c,
+ 0x6f, 0x61, 0x64,
+
+ 0x00, 0x03, 0x00, 0x04, // Validation Alg, length 4
+ 0x00, 0x02, 0x00, 0x00, // CRC32, length 0
+
+ 0x00, 0x04, 0x00, 0x04, // Validation Payload, length 4
+ 0x7e, 0x60, 0x54, 0xc4, // The payload (the CRC32)
+};
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_ComputeContentObjectHash)
+{
+ PARCBuffer *wireFormatBuffer = parcBuffer_Wrap(_v1_ContentObject_WithKnownHash, sizeof(_v1_ContentObject_WithKnownHash),
+ 0, sizeof(_v1_ContentObject_WithKnownHash));
+
+ CCNxWireFormatMessage *message = ccnxWireFormatMessage_Create(wireFormatBuffer);
+
+ CCNxTlvDictionary *contentObject = ccnxWireFormatMessage_GetDictionary(message);
+
+ // We have a partially unpacked dictionary now, but we need to more fully unpack it for our processing.
+ assertTrue(ccnxCodecTlvPacket_BufferDecode(wireFormatBuffer, contentObject), "Expected to decode the wireformat buffer");
+
+
+ PARCCryptoHash *coHash = _ccnxWireFormatFacadeV1_ComputeContentObjectHash(contentObject);
+
+ assertNotNull(coHash, "Expected a non-NULL content object hash");
+
+ char *computedHash = parcBuffer_ToHexString(parcCryptoHash_GetDigest(coHash));
+
+ char *knownHash = "4FB301EA5FD523B9A71287B721DC20C94B2D4827674A8CA275B7D57C60447876";
+
+ assertTrue(strncasecmp(computedHash, knownHash, strlen(knownHash)) == 0, "Expected a matching ContentObject hash");
+
+ parcMemory_Deallocate(&computedHash);
+ parcCryptoHash_Release(&coHash);
+ parcBuffer_Release(&wireFormatBuffer);
+
+ ccnxContentObject_Release(&contentObject);
+}
+
+// =======================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _ccnxWireFormatFacadeV1_ComputeHash);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+LONGBOW_TEST_CASE(Local, _ccnxWireFormatFacadeV1_ComputeHash)
+{
+ // >1234<
+ const char string[] = "Hello dev null\n";
+ const char substring[] = " dev";
+
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+ size_t start = 5;
+ size_t length = 4;
+
+
+ // compute the true hash
+ PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
+ parcCryptoHasher_Init(hasher);
+ parcCryptoHasher_UpdateBytes(hasher, substring, length);
+ PARCCryptoHash *truthHash = parcCryptoHasher_Finalize(hasher);
+
+ // Compute the test hash
+ PARCCryptoHash *testHash = _ccnxWireFormatFacadeV1_ComputeBufferHash(buffer, hasher, start, length);
+
+ // Test
+ bool equals = parcCryptoHash_Equals(truthHash, testHash);
+ assertTrue(equals, "Hashes do not match")
+ {
+ PARCBuffer *truthBuffer = parcCryptoHash_GetDigest(truthHash);
+ PARCBuffer *testBuffer = parcCryptoHash_GetDigest(testHash);
+
+ printf("Expected:\n");
+ parcBuffer_Display(truthBuffer, 3);
+
+ printf("Got:\n");
+ parcBuffer_Display(testBuffer, 3);
+ }
+
+ parcCryptoHash_Release(&truthHash);
+ parcCryptoHash_Release(&testHash);
+ parcBuffer_Release(&buffer);
+ parcCryptoHasher_Release(&hasher);
+}
+
+// =======================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_WireFormatFacade);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}