aboutsummaryrefslogtreecommitdiffstats
path: root/libccnx-common/ccnx/common/codec/schema_v1
diff options
context:
space:
mode:
authorLuca Muscariello <lumuscar+fdio@cisco.com>2017-02-23 20:44:26 +0100
committerLuca Muscariello <lumuscar+fdio@cisco.com>2017-02-23 19:51:14 +0000
commitd18ae43123fcd7604d1c36a1ec8450dbe6071824 (patch)
tree2d49fc3aabd0f2607251c854565648d47b56b2e9 /libccnx-common/ccnx/common/codec/schema_v1
parent9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff)
Initial commit: ccnxlibs.
Change-Id: I1b376527a7dd01a6b9e083a6cb646955902f45c0 Signed-off-by: Luca Muscariello <lumuscar+fdio@cisco.com>
Diffstat (limited to 'libccnx-common/ccnx/common/codec/schema_v1')
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.c137
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.h85
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h51
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.c210
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.h165
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.c64
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.h50
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.c149
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.h74
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.c165
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.h76
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.c187
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.h52
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.c166
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.h31
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.c140
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.h57
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c340
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.h47
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.c85
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h83
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.c59
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.h64
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.c125
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.h144
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.c187
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.h46
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.c289
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.h91
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.c353
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.h85
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.c68
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h250
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h211
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.c176
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.h74
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.c253
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.h79
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/.gitignore19
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/CMakeLists.txt29
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_CryptoSuite.c154
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_FixedHeaderDecoder.c350
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_FixedHeaderEncoder.c174
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_HashCodec.c235
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_LinkCodec.c450
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ManifestDecoder.c267
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ManifestEncoder.c306
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_MessageDecoder.c320
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_MessageEncoder.c644
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_NameCodec.c139
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_NameSegmentCodec.c149
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_OptionalHeadersDecoder.c321
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_OptionalHeadersEncoder.c205
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_PacketDecoder.c684
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_PacketEncoder.c1054
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_TlvDictionary.c118
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ValidationDecoder.c450
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ValidationEncoder.c565
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/testrig_encoder.c472
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/test/testrig_packetwrapper.c516
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/CMakeLists.txt27
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_CPISchema.h50
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h74
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h54
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameA_crc32c.h114
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h181
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameless_nosig.h65
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_no_payload.h55
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_zero_payload.h57
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route.h50
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route_crc32c.h78
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h102
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_bad_message_length.h57
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_bad_validation_alg.h74
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA.h75
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_badcrc32c.h76
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_crc32c.h102
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_validation_alg_overrun.h74
-rw-r--r--libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_testrig_truthSet.h68
-rwxr-xr-xlibccnx-common/ccnx/common/codec/schema_v1/testdata/v1_testrig_truthTable.h34
80 files changed, 14056 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.c
new file mode 100755
index 00000000..588694b0
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.c
@@ -0,0 +1,137 @@
+/*
+ * 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/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.h>
+
+
+bool
+ccnxCodecSchemaV1CryptoSuite_ParcToTlv(PARCCryptoSuite parcSuite, CCNxCodecSchemaV1TlvDictionary_CryptoSuite *outputValue)
+{
+ bool matchFound = false;
+ switch (parcSuite) {
+ case PARCCryptoSuite_RSA_SHA256:
+ *outputValue = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256;
+ matchFound = true;
+ break;
+
+ case PARCCryptoSuite_DSA_SHA256:
+ // not supported yet
+ break;
+
+ case PARCCryptoSuite_RSA_SHA512:
+ // not supported yet
+ break;
+
+ case PARCCryptoSuite_HMAC_SHA256:
+ *outputValue = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256;
+ matchFound = true;
+ break;
+
+ case PARCCryptoSuite_HMAC_SHA512:
+ // not supported yet
+ break;
+
+ case PARCCryptoSuite_NULL_CRC32C:
+ *outputValue = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C;
+ matchFound = true;
+ break;
+
+ default:
+ // unknown
+ break;
+ }
+ return matchFound;
+}
+
+bool
+ccnxCodecSchemaV1CryptoSuite_TlvToParc(CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvValue, PARCCryptoSuite *outputSuite)
+{
+ bool matchFound = false;
+ switch (tlvValue) {
+ case CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256:
+ *outputSuite = PARCCryptoSuite_RSA_SHA256;
+ matchFound = true;
+ break;
+
+ case CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C:
+ *outputSuite = PARCCryptoSuite_NULL_CRC32C;
+ matchFound = true;
+ break;
+
+ case CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256:
+ *outputSuite = PARCCryptoSuite_HMAC_SHA256;
+ matchFound = true;
+ break;
+
+ case CCNxCodecSchemaV1TlvDictionary_CryptoSuite_EcSecp256K1:
+ // not supported yet
+ break;
+
+ default:
+ // unknown
+ break;
+ }
+ return matchFound;
+}
+
+bool
+ccnxCodecSchemaV1CryptoSuite_SignAndHashToTlv(PARCSigningAlgorithm signAlgorithm, PARCCryptoHashType hashType, CCNxCodecSchemaV1TlvDictionary_CryptoSuite *outputValue)
+{
+ bool matchFound = false;
+ switch (signAlgorithm) {
+ case PARCSigningAlgorithm_RSA: {
+ switch (hashType) {
+ case PARCCryptoHashType_SHA256:
+ *outputValue = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256;
+ matchFound = true;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ case PARCSigningAlgorithm_HMAC: {
+ switch (hashType) {
+ case PARCCryptoHashType_SHA256:
+ *outputValue = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256;
+ matchFound = true;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case PARCSigningAlgortihm_NULL: {
+ switch (hashType) {
+ case PARCCryptoHashType_CRC32C:
+ *outputValue = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C;
+ matchFound = true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return matchFound;
+}
+
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.h
new file mode 100755
index 00000000..68e90749
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.h
@@ -0,0 +1,85 @@
+/*
+ * 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 ccnxCodecSchemaV1_CryptoSuite.h
+ * @brief Translates between PARC CryptoSuite values and the wire encoding
+ *
+ * <#Detailed Description#>
+ *
+ */
+
+#include <stdbool.h>
+#include <parc/security/parc_CryptoHashType.h>
+#include <parc/security/parc_SigningAlgorithm.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+/**
+ * Converts a PARC Crypto Suite to its TLV value
+ *
+ * Looks up the PARC cryptosuite value and returns the corresponding TLV wire format value.
+ * If no match is found, returns false and outputSuite is not modified.
+ *
+ *
+ * @param [in] parcSuite The PARC cryptosuite
+ * @param [out] outputValue The wire encoding equivalent
+ *
+ * @retval true if supported suite and outputValue set.
+ * @retval false if not supported.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1CryptoSuite_ParcToTlv(PARCCryptoSuite parcSuite, CCNxCodecSchemaV1TlvDictionary_CryptoSuite *outputValue);
+
+/**
+ * Converts a wire format cryptosuite value to the PARC cryptosuite
+ *
+ * Looks up the TLV wire format value and returns the corresponding PARC cryptosuite.
+ * If no match is found, returns false and outputSuite is not modified.
+ *
+ * @param [in] tlvValue The wire format value
+ * @param [out] outputValue The PARC equivalent
+ *
+ * @return true if match found and parcSuite set.
+ * @return false if no match found.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1CryptoSuite_TlvToParc(CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvValue, PARCCryptoSuite *outputSuite);
+
+/**
+ * Lookup a signing algorithm and hash type and convert to a wire format value
+ *
+ * Based on a PARCSigner's algorithm and hash type, find the corresponding wire format crypto suite.
+ *
+ * @param [in] signAlgorithm The signing algorithm
+ * @param [in] hashType The hash used by the signing algorithm
+ * @param [out] outputValue The wire format value
+ *
+ * @retval true if supported suite and outputValue set.
+ * @retval false if not supported.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1CryptoSuite_SignAndHashToTlv(PARCSigningAlgorithm signAlgorithm, PARCCryptoHashType hashType, CCNxCodecSchemaV1TlvDictionary_CryptoSuite *outputValue);
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h
new file mode 100755
index 00000000..3055c054
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h
@@ -0,0 +1,51 @@
+/*
+ * 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 ccnxCodecSchemaV1_FixedHeader.h
+ * @brief common definitions and functions for the FixedHeader
+ *
+ * See ccnxCodecSchemaV1_Packet.h for an overview of the version 1 codec
+ *
+ * This is the one file you need to include for all FixedHeader operations. It will
+ * include all the Decoders and Encoders.
+ *
+ */
+
+#ifndef TransportRTA_ccnxCodecSchemaV1_FixedHeader_h
+#define TransportRTA_ccnxCodecSchemaV1_FixedHeader_h
+
+typedef struct __attribute__ ((__packed__)) rta_tlv_schema_v1_fixed_header {
+ uint8_t version;
+ uint8_t packetType;
+ uint16_t packetLength;
+ uint8_t reserved[3];
+ uint8_t headerLength;
+} CCNxCodecSchemaV1FixedHeader;
+
+typedef struct __attribute__ ((__packed__)) rta_tlv_schema_v1_interest_header {
+ uint8_t version;
+ uint8_t packetType;
+ uint16_t packetLength;
+ uint8_t hopLimit;
+ uint8_t returnCode;
+ uint8_t flags;
+ uint8_t headerLength;
+} CCNxCodecSchemaV1InterestHeader;
+
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.h>
+#endif // TransportRTA_ccnxCodecSchemaV1_FixedHeader_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.c
new file mode 100755
index 00000000..fcec49b3
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.c
@@ -0,0 +1,210 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+
+static const size_t _fixedHeaderBytes = 8;
+
+static const int _fixedHeader_VersionOffset = 0;
+static const int _fixedHeader_PacketTypeOffset = 1;
+static const int _fixedHeader_PacketLengthOffset = 2;
+static const int _fixedHeader_HopLimitOffset = 4;
+static const int _fixedHeader_ReturnCodeOffset = 5;
+static const int _fixedHeader_FlagsOffset = 6;
+static const int _fixedHeader_HeaderLengthOffset = 7;
+
+bool
+ccnxCodecSchemaV1FixedHeaderDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary)
+{
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, _fixedHeaderBytes)) {
+ PARCBuffer *buffer = ccnxCodecTlvDecoder_GetValue(decoder, _fixedHeaderBytes);
+ bool success = ccnxTlvDictionary_PutBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader, buffer);
+
+ // validation
+ parcBuffer_SetPosition(buffer, _fixedHeader_VersionOffset);
+ uint8_t version = parcBuffer_GetUint8(buffer);
+
+ parcBuffer_SetPosition(buffer, _fixedHeader_PacketLengthOffset);
+ uint16_t packetLength = parcBuffer_GetUint16(buffer);
+
+ parcBuffer_SetPosition(buffer, _fixedHeader_ReturnCodeOffset);
+ uint8_t interestReturnCode = parcBuffer_GetUint8(buffer);
+
+ parcBuffer_SetPosition(buffer, _fixedHeader_HopLimitOffset);
+ uint8_t hopLimit = parcBuffer_GetUint8(buffer);
+
+ parcBuffer_SetPosition(buffer, _fixedHeader_HeaderLengthOffset);
+ uint8_t headerLength = parcBuffer_GetUint8(buffer);
+
+ if (version != 1) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_VERSION, __func__, __LINE__, _fixedHeader_VersionOffset);
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ success = false;
+ } else if (packetLength < _fixedHeaderBytes) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETLENGTH_TOO_SHORT, __func__, __LINE__, _fixedHeader_PacketTypeOffset);
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ success = false;
+ } else if (headerLength < _fixedHeaderBytes) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_HEADERLENGTH_TOO_SHORT, __func__, __LINE__, _fixedHeader_HeaderLengthOffset);
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ success = false;
+ } else if (packetLength < headerLength) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETLENGTHSHORTER, __func__, __LINE__, _fixedHeader_PacketTypeOffset);
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ success = false;
+ }
+
+ // decoder now points to just past the fixed header
+ parcBuffer_Release(&buffer);
+
+ // Set the hoplimit in the dictionary.
+ ccnxTlvDictionary_PutInteger(packetDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT, hopLimit);
+
+ // Set the InterestReturn code in the dictionary.
+ ccnxTlvDictionary_PutInteger(packetDictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestReturnCode,
+ interestReturnCode);
+
+ return success;
+ } else {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ return false;
+ }
+}
+
+int
+ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion(CCNxTlvDictionary *packetDictionary)
+{
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+ if (fixedHeader != NULL) {
+ parcBuffer_SetPosition(fixedHeader, _fixedHeader_VersionOffset);
+ uint8_t version = parcBuffer_GetUint8(fixedHeader);
+ return version;
+ }
+
+ return -1;
+}
+
+int
+ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketType(CCNxTlvDictionary *packetDictionary)
+{
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+ if (fixedHeader != NULL) {
+ parcBuffer_SetPosition(fixedHeader, _fixedHeader_PacketTypeOffset);
+ uint8_t packetType = parcBuffer_GetUint8(fixedHeader);
+ return packetType;
+ }
+
+ return -1;
+}
+
+int
+ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength(CCNxTlvDictionary *packetDictionary)
+{
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+ if (fixedHeader != NULL) {
+ parcBuffer_SetPosition(fixedHeader, _fixedHeader_PacketLengthOffset);
+ uint16_t payloadLength = parcBuffer_GetUint16(fixedHeader);
+ return payloadLength;
+ }
+
+ return -1;
+}
+
+int
+ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength(CCNxTlvDictionary *packetDictionary)
+{
+ int length = -1;
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+ if (fixedHeader != NULL) {
+ parcBuffer_SetPosition(fixedHeader, _fixedHeader_HeaderLengthOffset);
+ uint8_t headerLength = parcBuffer_GetUint8(fixedHeader);
+
+ // 8 is the minimum size of headerLength
+ if (headerLength >= _fixedHeaderBytes) {
+ length = headerLength;
+ }
+ }
+
+ return length;
+}
+
+int
+ccnxCodecSchemaV1FixedHeaderDecoder_GetOptionalHeaderLength(CCNxTlvDictionary *packetDictionary)
+{
+ int headerLength = ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength(packetDictionary);
+ return headerLength - _fixedHeaderBytes;
+}
+
+int
+ccnxCodecSchemaV1FixedHeaderDecoder_GetHopLimit(CCNxTlvDictionary *packetDictionary)
+{
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+ if (fixedHeader != NULL) {
+ parcBuffer_SetPosition(fixedHeader, _fixedHeader_HopLimitOffset);
+ uint8_t hopLimit = parcBuffer_GetUint8(fixedHeader);
+ return hopLimit;
+ }
+
+ return -1;
+}
+
+int
+ccnxCodecSchemaV1FixedHeaderDecoder_GetReturnCode(CCNxTlvDictionary *packetDictionary)
+{
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+ if (fixedHeader != NULL) {
+ parcBuffer_SetPosition(fixedHeader, _fixedHeader_ReturnCodeOffset);
+ uint8_t returnCode = parcBuffer_GetUint8(fixedHeader);
+ return returnCode;
+ }
+
+ return -1;
+}
+
+int
+ccnxCodecSchemaV1FixedHeaderDecoder_GetFlags(CCNxTlvDictionary *packetDictionary)
+{
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+ if (fixedHeader != NULL) {
+ parcBuffer_SetPosition(fixedHeader, _fixedHeader_FlagsOffset);
+ uint8_t flags = parcBuffer_GetUint8(fixedHeader);
+ return flags;
+ }
+
+ return -1;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.h
new file mode 100755
index 00000000..5d15f40b
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderDecoder.h
@@ -0,0 +1,165 @@
+/*
+ * 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 Libccnx_ccnxCodecSchemaV1_FixedHeaderDecoder_h
+#define Libccnx_ccnxCodecSchemaV1_FixedHeaderDecoder_h
+
+#include <stdbool.h>
+
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+
+/**
+ * The decode a V1 fixed header
+ *
+ * The decoder should point to byte 0 of the Fixed Header.
+ * It will be advanced to the first byte following it.
+ * The results are put in the provided.
+ *
+ * @param [in] decoder The decoder to parse
+ * @param [in] dictionary The results go directly in to the provided dictionary.
+ *
+ * @return true Fully parsed interest, no errors
+ * @return false Error decoding, decoder is left pointing to the first byte of the error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1FixedHeaderDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the version
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] fixedHeaderDictionary The FixedHeader dictionary
+ *
+ * @return positive The Version
+ * @return -1 The field does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+int ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the PacketType
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] fixedHeaderDictionary The FixedHeader dictionary
+ *
+ * @return positive The PacketType
+ * @return -1 The field does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+int ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketType(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the PacketLength
+ *
+ * The PacketLength is measured from byte 0 to the end of the packet
+ *
+ * @param [in] fixedHeaderDictionary The FixedHeader dictionary
+ *
+ * @return positive The packet length (in host byte order)
+ * @return -1 The field does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+int ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the HeaderLength
+ *
+ * In a version 1 packet, the header length includes the fixed header. It is measured from
+ * byte 0 to the end of the hop-by-hop headers.
+ *
+ * @param [in] fixedHeaderDictionary The FixedHeader dictionary
+ *
+ * @return positive The header length
+ * @return -1 The field does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+int ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * Returns the bytes of the optional headers
+ *
+ * Computes ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength() - sizeof(fixedHeader)
+ *
+ * @param [in] fixedHeaderDictionary The FixedHeader dictionary
+ *
+ * @retval non-negative The length of the optional headers
+ * @retval negative An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+int ccnxCodecSchemaV1FixedHeaderDecoder_GetOptionalHeaderLength(CCNxTlvDictionary *packetDictionary);
+
+
+/**
+ * A convenience function to return the ReturnCode of an Interest or InterestReturn
+ *
+ * @param [in] fixedHeaderDictionary The FixedHeader dictionary
+ *
+ * @return positive The Return Code
+ * @return -1 The field does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+int ccnxCodecSchemaV1FixedHeaderDecoder_GetReturnCode(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the header Flags
+ *
+ * @param [in] fixedHeaderDictionary The FixedHeader dictionary
+ *
+ * @return positive The flags
+ * @return -1 The field does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+int ccnxCodecSchemaV1FixedHeaderDecoder_GetFlags(CCNxTlvDictionary *packetDictionary);
+
+#endif // Libccnx_ccnxCodecSchemaV1_FixedHeaderDecoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.c
new file mode 100755
index 00000000..3b6eca67
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.c
@@ -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.
+ */
+
+/**
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include <LongBow/runtime.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+
+ssize_t
+ccnxCodecSchemaV1FixedHeaderEncoder_EncodeHeader(CCNxCodecTlvEncoder *fixedHeaderEncoder, const CCNxCodecSchemaV1FixedHeader *header)
+{
+ assertNotNull(fixedHeaderEncoder, "Parameter fixedHeaderEncoder must be non-null");
+ assertNotNull(header, "Parameter header must be non-null");
+ trapIllegalValueIf(header->version != 1, "Header wrong version, must be 1");
+
+ CCNxCodecSchemaV1InterestHeader copy;
+
+ memcpy(&copy, header, sizeof(CCNxCodecSchemaV1InterestHeader));
+
+ copy.packetLength = htons(header->packetLength);
+
+ switch (header->packetType) {
+ case CCNxCodecSchemaV1Types_PacketType_Interest:
+ copy.returnCode = 0;
+ break;
+
+ case CCNxCodecSchemaV1Types_PacketType_InterestReturn:
+ // nothing to do, all fields used
+ break;
+
+ default:
+ copy.hopLimit = 0;
+ copy.returnCode = 0;
+ copy.flags = 0;
+ break;
+ }
+
+ ccnxCodecTlvEncoder_AppendRawArray(fixedHeaderEncoder, sizeof(CCNxCodecSchemaV1FixedHeader), (uint8_t *) &copy);
+ return sizeof(CCNxCodecSchemaV1FixedHeader);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.h
new file mode 100755
index 00000000..0981f4bd
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.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 ccnxCodecSchemaV1_FixedHeaderEncoder.h
+ * @brief <#Brief Description#>
+ *
+ * <#Detailed Description#>
+ *
+ */
+#ifndef Libccnx_ccnxCodecSchemaV1_FixedHeaderEncoder_h
+#define Libccnx_ccnxCodecSchemaV1_FixedHeaderEncoder_h
+
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h>
+
+/**
+ * Set the values in the fixed header
+ *
+ * Put the provided fixed header at the given byte location. The provided fixed header is not put
+ * in as-is (i.e byte for byte), but is parsed and put in the correct byte positions and encodings
+ * assuming the fixed header starts at the given position.
+ *
+ * The encoder is returned to its current position after putting the header.
+ *
+ * @param [in] encoder The encoder to append the fixed header in to
+ * @param [in] The header, in host byte order
+ *
+ * @return Number The bytes appended, or -1 on error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+ssize_t ccnxCodecSchemaV1FixedHeaderEncoder_EncodeHeader(CCNxCodecTlvEncoder *encoder, const CCNxCodecSchemaV1FixedHeader *header);
+#endif // Libccnx_ccnxCodecSchemaV1_FixedHeaderEncoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.c
new file mode 100644
index 00000000..23a559cc
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.c
@@ -0,0 +1,149 @@
+/*
+ * 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 <LongBow/runtime.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.h>
+
+/**
+ * These are the accepted sizes for the pre-defined hash types.
+ * Hash TLVs with lengths that do not match one of these values will be deemed
+ * invalid and not parse correctly.
+ */
+static const size_t _PARCCryptoHashType_SHA256_Sizes[] = { 32 };
+static const size_t _PARCCryptoHashType_SHA512_Sizes[] = { 32, 64 };
+
+static bool
+_ccnxCodecSchemaV1HashCodec_ValidHashSize(size_t size, size_t numSizes, size_t sizes[numSizes])
+{
+ for (size_t i = 0; i < numSizes; i++) {
+ if (sizes[i] == size) {
+ return true;
+ }
+ }
+ return false;
+}
+
+ssize_t
+ccnxCodecSchemaV1HashCodec_Encode(CCNxCodecTlvEncoder *encoder, const PARCCryptoHash *hash)
+{
+ PARCBuffer *digest = parcCryptoHash_GetDigest(hash);
+ PARCCryptoHashType hashType = parcCryptoHash_GetDigestType(hash);
+ size_t digestLength = parcBuffer_Remaining(digest);
+
+ uint16_t tlvHashType = CCNxCodecSchemaV1Types_HashType_App;
+ bool validHash = true;
+ switch (hashType) {
+ case PARCCryptoHashType_SHA256:
+ tlvHashType = CCNxCodecSchemaV1Types_HashType_SHA256;
+ validHash = _ccnxCodecSchemaV1HashCodec_ValidHashSize(digestLength,
+ sizeof(_PARCCryptoHashType_SHA256_Sizes) / sizeof(size_t), (size_t *) _PARCCryptoHashType_SHA256_Sizes);
+ break;
+ case PARCCryptoHashType_SHA512:
+ tlvHashType = CCNxCodecSchemaV1Types_HashType_SHA512;
+ validHash = _ccnxCodecSchemaV1HashCodec_ValidHashSize(digestLength,
+ sizeof(_PARCCryptoHashType_SHA512_Sizes) / sizeof(size_t), (size_t *) _PARCCryptoHashType_SHA512_Sizes);
+ break;
+ default:
+ break;
+ }
+
+ if (validHash) {
+ return ccnxCodecTlvEncoder_AppendBuffer(encoder, tlvHashType, digest);
+ } else {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_MISSING_MANDATORY, __func__, __LINE__, ccnxCodecTlvEncoder_Position(encoder));
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+
+ return -1;
+ }
+}
+
+static bool
+_ccnxCodecSchemaV1HashCodec_ValidHash(uint16_t hashType, uint16_t hashSize)
+{
+ bool validHash = true;
+
+ switch (hashType) {
+ case CCNxCodecSchemaV1Types_HashType_SHA256:
+ validHash = _ccnxCodecSchemaV1HashCodec_ValidHashSize(hashSize,
+ sizeof(_PARCCryptoHashType_SHA256_Sizes) / sizeof(size_t), (size_t *) _PARCCryptoHashType_SHA256_Sizes);
+ break;
+ case CCNxCodecSchemaV1Types_HashType_SHA512:
+ validHash = _ccnxCodecSchemaV1HashCodec_ValidHashSize(hashSize,
+ sizeof(_PARCCryptoHashType_SHA512_Sizes) / sizeof(size_t), (size_t *) _PARCCryptoHashType_SHA512_Sizes);
+ break;
+ default:
+ break;
+ }
+
+ return validHash;
+}
+
+PARCCryptoHash *
+ccnxCodecSchemaV1HashCodec_DecodeValue(CCNxCodecTlvDecoder *decoder, size_t limit)
+{
+ PARCCryptoHash *hash = NULL;
+ uint16_t hashType = 0;
+ uint16_t length = 0;
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, 4)) {
+ hashType = ccnxCodecTlvDecoder_GetType(decoder);
+ length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ if (length > limit) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_MISSING_MANDATORY, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ return NULL;
+ }
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, length)) {
+ PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(decoder, length);
+ switch (hashType) {
+ case CCNxCodecSchemaV1Types_HashType_SHA256:
+ hash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, value);
+ break;
+ case CCNxCodecSchemaV1Types_HashType_SHA512:
+ hash = parcCryptoHash_Create(PARCCryptoHashType_SHA512, value);
+ break;
+ case CCNxCodecSchemaV1Types_HashType_App:
+ hash = parcCryptoHash_Create(PARCCryptoHashType_NULL, value);
+ break;
+ }
+ parcBuffer_Release(&value);
+ }
+ }
+
+ // Verify the hash size, if one was parsed correctly.
+ if (hash != NULL && !_ccnxCodecSchemaV1HashCodec_ValidHash(hashType, length)) {
+ parcCryptoHash_Release(&hash);
+ }
+
+ return hash;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.h
new file mode 100755
index 00000000..f03b3746
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.h
@@ -0,0 +1,74 @@
+/*
+ * 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 ccnxCodecSchemaV1_HashCodec.h
+ * @brief A cryptographic hash digest encoded
+ *
+ */
+
+#ifndef __CCNx_Common__ccnxCodecSchemaV1_HashCodec__
+#define __CCNx_Common__ccnxCodecSchemaV1_HashCodec__
+
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+
+#include <parc/security/parc_CryptoHash.h>
+
+/**
+ * Encodes the hash, but without a "TL" container
+ *
+ * Will append the Link in it's well-known TLV format, but without any
+ * "TL" container.
+ *
+ * If the link does not have a name, will return -1 with the error TLV_MISSING_MANDATORY.
+ *
+ * @param [in] encoder The hash will be appended to the encoder
+ * @param [in] hash The hash to append
+ *
+ * @retval non-negative The number of bytes appended to the encoder
+ * @retval negative An error, look at the CCNxCodecError of the encoder
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+ssize_t ccnxCodecSchemaV1HashCodec_Encode(CCNxCodecTlvEncoder *encoder, const PARCCryptoHash *hash);
+
+/**
+ * The decoder points to the first byte of the "value" of something that is a Link
+ *
+ * For a KeyName, decoder should be pointed to the "value" of the KeyName. for a ContentObject
+ * of type Link, it should be the first byte of the Payload.
+ *
+ * A link is the tuple {Name, [KeyId], [Hash]}, where KeyId is the keyIdRestriction and
+ * Hash is the ContentObjectHash restriction to use in an Interest for Name.
+ * No additional fields are allowed in the Link.
+ *
+ * @param [in] decoder The Tlv Decoder pointing to the start of the Name value
+ * @param [in] length the length of the Hash value
+ *
+ * @return non-null A parsed name
+ * @return null An error, check the decoder's error message
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+PARCCryptoHash *ccnxCodecSchemaV1HashCodec_DecodeValue(CCNxCodecTlvDecoder *decoder, size_t length);
+
+#endif // __CCNx_Common__ccnxCodecSchemaV1_HashCodec__
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.c
new file mode 100755
index 00000000..cc78c28e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.c
@@ -0,0 +1,165 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.h>
+
+ssize_t
+ccnxCodecSchemaV1LinkCodec_Encode(CCNxCodecTlvEncoder *encoder, const CCNxLink *link)
+{
+ ssize_t length = 0;
+
+ const CCNxName *name = ccnxLink_GetName(link);
+ if (name) {
+ length += ccnxCodecSchemaV1NameCodec_Encode(encoder, CCNxCodecSchemaV1Types_Link_Name, name);
+
+ PARCBuffer *keyid = ccnxLink_GetKeyID(link);
+ if (keyid) {
+ length += ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_Link_KeyIdRestriction, keyid);
+ }
+
+ PARCBuffer *hash = ccnxLink_GetContentObjectHash(link);
+ if (hash) {
+ length += ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_Link_ContentObjectHashRestriction, hash);
+ }
+ } else {
+ length = -1;
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_MISSING_MANDATORY, __func__, __LINE__, ccnxCodecTlvEncoder_Position(encoder));
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+ }
+
+ return length;
+}
+
+typedef struct decoded_link {
+ CCNxName *linkName;
+ PARCBuffer *linkKeyId;
+ PARCBuffer *linkHash;
+} _DecodedLink;
+
+static int
+_decodeField(CCNxCodecTlvDecoder *decoder, _DecodedLink *decodedLink)
+{
+ int errorCode = TLV_ERR_NO_ERROR;
+
+ uint16_t type = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, length)) {
+ switch (type) {
+ case CCNxCodecSchemaV1Types_Link_Name:
+ if (decodedLink->linkName == NULL) {
+ decodedLink->linkName = ccnxCodecSchemaV1NameCodec_DecodeValue(decoder, length);
+ } else {
+ errorCode = TLV_ERR_DUPLICATE_FIELD;
+ }
+ break;
+
+ case CCNxCodecSchemaV1Types_Link_KeyIdRestriction:
+ if (decodedLink->linkKeyId == NULL) {
+ decodedLink->linkKeyId = ccnxCodecTlvDecoder_GetValue(decoder, length);
+ } else {
+ errorCode = TLV_ERR_DUPLICATE_FIELD;
+ }
+ break;
+
+ case CCNxCodecSchemaV1Types_Link_ContentObjectHashRestriction:
+ if (decodedLink->linkHash == NULL) {
+ decodedLink->linkHash = ccnxCodecTlvDecoder_GetValue(decoder, length);
+ } else {
+ errorCode = TLV_ERR_DUPLICATE_FIELD;
+ }
+ break;
+
+ default:
+ // we do not support unknown TLVs
+ errorCode = TLV_ERR_DECODE;
+ break;
+ }
+ } else {
+ errorCode = TLV_ERR_TOO_LONG;
+ }
+
+ return errorCode;
+}
+
+static void
+_decodecLinkCleanup(_DecodedLink *decodedLink)
+{
+ if (decodedLink->linkName) {
+ ccnxName_Release(&decodedLink->linkName);
+ }
+
+ if (decodedLink->linkKeyId) {
+ parcBuffer_Release(&decodedLink->linkKeyId);
+ }
+
+ if (decodedLink->linkHash) {
+ parcBuffer_Release(&decodedLink->linkHash);
+ }
+}
+
+CCNxLink *
+ccnxCodecSchemaV1LinkCodec_DecodeValue(CCNxCodecTlvDecoder *decoder, uint16_t linkLength)
+{
+ int errorCode = TLV_ERR_NO_ERROR;
+
+ CCNxLink *link = NULL;
+
+ _DecodedLink decodedLink;
+ memset(&decodedLink, 0, sizeof(_DecodedLink));
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, linkLength)) {
+ while (errorCode == TLV_ERR_NO_ERROR && ccnxCodecTlvDecoder_EnsureRemaining(decoder, 4)) {
+ errorCode = _decodeField(decoder, &decodedLink);
+ }
+ } else {
+ errorCode = TLV_ERR_TOO_LONG;
+ }
+
+ if (errorCode == TLV_ERR_NO_ERROR && decodedLink.linkName == NULL) {
+ errorCode = TLV_ERR_DECODE;
+ }
+
+ if (errorCode != TLV_ERR_NO_ERROR) {
+ CCNxCodecError *error = ccnxCodecError_Create(errorCode, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ } else {
+ link = ccnxLink_Create(decodedLink.linkName, decodedLink.linkKeyId, decodedLink.linkHash);
+ }
+
+ // cleanup any partial memory allocations
+ _decodecLinkCleanup(&decodedLink);
+
+ return link;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.h
new file mode 100755
index 00000000..4163aa1d
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.h
@@ -0,0 +1,76 @@
+/*
+ * 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 ccnxCodecSchemaV1_LinkCodec.h
+ * @brief A Link is a well-known value, not a TLV field
+ *
+ * A Link may be the "value" of a TLV element, such as the KeyName. It can also occur
+ * in the payload of a ContentObject whose PayloadType is Link.
+ *
+ */
+
+#ifndef __CCNx_Common__ccnxCodecSchemaV1_LinkCodec__
+#define __CCNx_Common__ccnxCodecSchemaV1_LinkCodec__
+
+#include <ccnx/common/ccnx_Link.h>
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+
+/**
+ * Encodes the link, but without a "TL" container
+ *
+ * Will append the Link in it's well-known TLV format, but without any
+ * "TL" container.
+ *
+ * If the link does not have a name, will return -1 with the error TLV_MISSING_MANDATORY.
+ *
+ * @param [in] encoder The link will be appended to the encoder
+ * @param [in] link The link to append
+ *
+ * @retval non-negative The number of bytes appended to the encoder
+ * @retval negative An error, look at the CCNxCodecError of the encoder
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+ssize_t ccnxCodecSchemaV1LinkCodec_Encode(CCNxCodecTlvEncoder *encoder, const CCNxLink *link);
+
+/**
+ * The decoder points to the first byte of the "value" of something that is a Link
+ *
+ * For a KeyName, decoder should be pointed to the "value" of the KeyName. for a ContentObject
+ * of type Link, it should be the first byte of the Payload.
+ *
+ * A link is the tuple {Name, [KeyId], [Hash]}, where KeyId is the keyIdRestriction and
+ * Hash is the ContentObjectHash restriction to use in an Interest for Name.
+ * No additional fields are allowed in the Link.
+ *
+ * @param [in] decoder The Tlv Decoder pointing to the start of the Name value
+ * @param [in] length the length of the Link value
+ *
+ * @return non-null A parsed name
+ * @return null An error, check the decoder's error message
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+CCNxLink *ccnxCodecSchemaV1LinkCodec_DecodeValue(CCNxCodecTlvDecoder *decoder, uint16_t length);
+
+#endif /* defined(__CCNx_Common__ccnxCodecSchemaV1_LinkCodec__) */
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.c
new file mode 100644
index 00000000..87665de1
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.c
@@ -0,0 +1,187 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.h>
+
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+#include <ccnx/common/ccnx_PayloadType.h>
+#include <ccnx/common/ccnx_InterestReturn.h>
+#include <ccnx/common/ccnx_Manifest.h>
+#include <ccnx/common/ccnx_ManifestHashGroup.h>
+
+static bool
+_decodeHashGroupMetadata(CCNxCodecTlvDecoder *decoder, CCNxManifestHashGroup *group, size_t length)
+{
+ size_t offset = 0;
+ bool success = true;
+
+ while (offset < length) {
+ uint16_t type = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t value_length = ccnxCodecTlvDecoder_GetLength(decoder);
+ PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(decoder, value_length);
+
+ offset += (4 + value_length);
+
+ switch (type) {
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator: {
+ char *nameString = parcBuffer_ToString(value);
+ const CCNxName *locator = ccnxName_CreateFromCString(nameString);
+ ccnxManifestHashGroup_SetLocator(group, locator);
+ parcMemory_Deallocate(&nameString);
+ ccnxName_Release((CCNxName **) &locator);
+ break;
+ }
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize: {
+ uint64_t dataSize = parcBuffer_GetUint64(value);
+ ccnxManifestHashGroup_SetDataSize(group, dataSize);
+ break;
+ }
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize: {
+ uint64_t blockSize = parcBuffer_GetUint64(value);
+ ccnxManifestHashGroup_SetBlockSize(group, blockSize);
+ break;
+ }
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize: {
+ uint64_t entrySize = parcBuffer_GetUint64(value);
+ ccnxManifestHashGroup_SetEntrySize(group, entrySize);
+ break;
+ }
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight: {
+ uint64_t treeHeight = parcBuffer_GetUint64(value);
+ ccnxManifestHashGroup_SetTreeHeight(group, treeHeight);
+ break;
+ }
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256: {
+ ccnxManifestHashGroup_SetOverallDataDigest(group, value);
+ break;
+ }
+ }
+
+ parcBuffer_Release(&value);
+ }
+
+ return success;
+}
+
+static bool
+_decodeHashGroup(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, CCNxManifestHashGroup *group, size_t length)
+{
+ bool success = true;
+ size_t offset = 0;
+
+ while (offset < length) {
+ uint16_t type = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t value_length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ offset += (4 + value_length);
+
+ switch (type) {
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata: {
+ success = _decodeHashGroupMetadata(decoder, group, value_length);
+ if (!success) {
+ return false;
+ }
+ break;
+ }
+
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroup_DataPointer: {
+ PARCBuffer *buffer = ccnxCodecTlvDecoder_GetValue(decoder, value_length);
+ ccnxManifestHashGroup_AppendPointer(group, CCNxManifestHashGroupPointerType_Data, buffer);
+ parcBuffer_Release(&buffer);
+ break;
+ }
+
+ case CCNxCodecSchemaV1Types_CCNxManifestHashGroup_ManifestPointer: {
+ PARCBuffer *buffer = ccnxCodecTlvDecoder_GetValue(decoder, value_length);
+ ccnxManifestHashGroup_AppendPointer(group, CCNxManifestHashGroupPointerType_Manifest, buffer);
+ parcBuffer_Release(&buffer);
+ break;
+ }
+
+ default:
+ // if we do not know the TLV type, put it in this container's unknown list
+ success = ccnxCodecTlvUtilities_PutAsListBuffer(decoder, packetDictionary, type, value_length, CCNxCodecSchemaV1TlvDictionary_Lists_MESSAGE_LIST);
+ break;
+ }
+
+ if (!success) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+ }
+
+ CCNxManifestInterface *manifest = ccnxManifestInterface_GetInterface(packetDictionary);
+ manifest->addHashGroup(packetDictionary, group);
+
+ return success;
+}
+
+static bool
+_decodeType(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length)
+{
+ bool success = false;
+ switch (type) {
+ case CCNxCodecSchemaV1Types_CCNxMessage_Name: {
+ success = ccnxCodecTlvUtilities_PutAsName(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME);
+ break;
+ }
+
+ case CCNxCodecSchemaV1Types_CCNxMessage_HashGroup: {
+ CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create();
+ success = _decodeHashGroup(decoder, packetDictionary, group, length);
+ ccnxManifestHashGroup_Release(&group);
+ break;
+ }
+
+ default:
+ // if we do not know the TLV type, put it in this container's unknown list
+ success = ccnxCodecTlvUtilities_PutAsListBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_Lists_MESSAGE_LIST);
+ break;
+ }
+
+ if (!success) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+ return success;
+}
+
+/*
+ * We are given a decoder that points to the first TLV of a list of TLVs. We keep walking the
+ * list until we come to the end of the decoder.
+ */
+bool
+ccnxCodecSchemaV1ManifestDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *manifestDictionary)
+{
+ return ccnxCodecTlvUtilities_DecodeContainer(decoder, manifestDictionary, _decodeType);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.h
new file mode 100755
index 00000000..1726e41e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.h
@@ -0,0 +1,52 @@
+/*
+ * 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 ccnxCodecSchemaV1_ManifestDecoder.h
+ * @brief Decode the body of a CCNx Manifest.
+ *
+ */
+
+#ifndef TransportRTA_ccnxCodecSchemaV1_ManifestDecoder_h
+#define TransportRTA_ccnxCodecSchemaV1_ManifestDecoder_h
+
+#include <stdbool.h>
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+
+/**
+ * Decode a V1 Manifest.
+ *
+ * The decoder should point to byte 0 of a Manifest (message) TLV.
+ * The results are put in the provided dictionary.
+ * It is an error if the message does not extend to the end of
+ * the decoder.
+ *
+ * @param [in] decoder The decoder to parse
+ * @param [in] manifestDictionary The results go directly in to the provided dictionary.
+ *
+ * @return true Fully parsed interest, no errors
+ * @return false Error decoding, decoder is left pointing to the first byte of the error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1ManifestDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *manifestDictionary);
+
+#endif // TransportRTA_ccnxCodecSchemaV1_ManifestDecoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.c
new file mode 100644
index 00000000..0d8f52bf
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.c
@@ -0,0 +1,166 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <parc/algol/parc_Buffer.h>
+#include <parc/algol/parc_BufferComposer.h>
+
+#include <ccnx/common/ccnx_Manifest.h>
+#include <ccnx/common/ccnx_ManifestHashGroup.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.h>
+
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+#include <ccnx/common/ccnx_PayloadType.h>
+#include <ccnx/common/ccnx_InterestReturn.h>
+
+static size_t
+_appendPointer(CCNxCodecTlvEncoder *encoder, CCNxManifestHashGroupPointer *ptr)
+{
+ const PARCBuffer *digest = ccnxManifestHashGroupPointer_GetDigest(ptr);
+ CCNxManifestHashGroupPointerType type = ccnxManifestHashGroupPointer_GetType(ptr);
+
+ ssize_t length = -1;
+ switch (type) {
+ case CCNxManifestHashGroupPointerType_Data:
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_DataPointer, (PARCBuffer *) digest);
+ break;
+ case CCNxManifestHashGroupPointerType_Manifest:
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_ManifestPointer, (PARCBuffer *) digest);
+ break;
+ default:
+ assertTrue(false, "Invalid pointer type %d", type);
+ }
+
+ if (length < 0) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_MISSING_MANDATORY, __func__, __LINE__, ccnxCodecTlvEncoder_Position(encoder));
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+ }
+
+ return length;
+}
+
+ssize_t
+_appendMetadata(CCNxCodecTlvEncoder *encoder, CCNxManifestHashGroup *group)
+{
+ ssize_t length = 0;
+
+ // Pre-populate this field -- we'll come back and fill in the length after we're done
+ size_t startPosition = ccnxCodecTlvEncoder_Position(encoder);
+ ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata, length);
+
+ // Now append all metadata that exists in the hash group.
+ const CCNxName *locator = ccnxManifestHashGroup_GetLocator(group);
+ if (locator != NULL) {
+ char *nameString = ccnxName_ToString(locator);
+ PARCBuffer *nameBuffer = parcBuffer_AllocateCString(nameString);
+ length += ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator, nameBuffer);
+ parcBuffer_Release(&nameBuffer);
+ parcMemory_Deallocate(&nameString);
+ }
+
+ size_t dataSize = ccnxManifestHashGroup_GetDataSize(group);
+ if (dataSize > 0) {
+ length += ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize, dataSize);
+ }
+
+ size_t blockSize = ccnxManifestHashGroup_GetBlockSize(group);
+ if (blockSize > 0) {
+ length += ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize, blockSize);
+ }
+
+ size_t entrySize = ccnxManifestHashGroup_GetEntrySize(group);
+ if (entrySize > 0) {
+ length += ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize, entrySize);
+ }
+
+ size_t treeSize = ccnxManifestHashGroup_GetTreeHeight(group);
+ if (treeSize > 0) {
+ length += ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight, treeSize);
+ }
+
+ const PARCBuffer *dataDigest = ccnxManifestHashGroup_GetOverallDataDigest(group);
+ if (dataDigest != NULL) {
+ length += ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256, (PARCBuffer *) dataDigest);
+ }
+
+ // Rewind back to the container opening and fill in the length
+ size_t endPosition = ccnxCodecTlvEncoder_Position(encoder);
+ ccnxCodecTlvEncoder_PutUint16(encoder, startPosition, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata);
+ ccnxCodecTlvEncoder_PutUint16(encoder, startPosition + 2, length);
+ ccnxCodecTlvEncoder_SetPosition(encoder, endPosition);
+
+ return endPosition - startPosition;
+}
+
+ssize_t
+ccnxCodecSchemaV1ManifestEncoder_Encode(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+
+ ssize_t numHashGroups = ccnxTlvDictionary_ListSize(packetDictionary, CCNxCodecSchemaV1TlvDictionary_Lists_HASH_GROUP_LIST);
+ for (size_t i = 0; i < numHashGroups; i++) {
+ // Skip past the TL of the hash group to append the pointers inside
+ ssize_t groupLength = 0;
+ ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_HashGroup, groupLength);
+
+ CCNxManifestInterface *interface = ccnxManifestInterface_GetInterface(packetDictionary);
+ CCNxManifestHashGroup *group = interface->getHashGroup(packetDictionary, i);
+
+ // Encode any metadata, if present.
+ if (ccnxManifestHashGroup_HasMetadata(group)) {
+ groupLength += _appendMetadata(encoder, group);
+ }
+
+ // Append the HashGroup pointers
+ size_t numPointers = ccnxManifestHashGroup_GetNumberOfPointers(group);
+ for (size_t p = 0; p < numPointers; p++) {
+ CCNxManifestHashGroupPointer *ptr = ccnxManifestHashGroup_GetPointerAtIndex(group, p);
+ ssize_t ptrLength = _appendPointer(encoder, ptr);
+ if (ptrLength < 0) {
+ return ptrLength;
+ }
+ groupLength += ptrLength;
+ }
+
+ // Now that we know the overall length, rewind back to the start and append the TL
+ // part of the container.
+ size_t endPosition = ccnxCodecTlvEncoder_Position(encoder);
+ ssize_t offset = endPosition - groupLength - 4;
+ ccnxCodecTlvEncoder_PutUint16(encoder, offset, CCNxCodecSchemaV1Types_CCNxMessage_HashGroup);
+ ccnxCodecTlvEncoder_PutUint16(encoder, offset + 2, groupLength);
+ ccnxCodecTlvEncoder_SetPosition(encoder, endPosition);
+
+ length += groupLength + 4;
+
+ ccnxManifestHashGroup_Release(&group);
+ }
+
+ return length;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.h
new file mode 100755
index 00000000..4951cf80
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.h
@@ -0,0 +1,31 @@
+/*
+ * 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 ccnxCodecSchemaV1_ManifestEncoder.h
+ * @brief Encode a V1 Manifest.
+ *
+ */
+
+#ifndef ccnx_common_ccnxCodecSchemaV1_ManifestEncoder_h
+#define ccnx_common_ccnxCodecSchemaV1_ManifestEncoder_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+
+ssize_t ccnxCodecSchemaV1ManifestEncoder_Encode(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary);
+
+#endif // ccnx_common_ccnxCodecSchemaV1_ManifestEncoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.c
new file mode 100644
index 00000000..f0dea7a6
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.c
@@ -0,0 +1,140 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.h>
+
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+#include <ccnx/common/ccnx_PayloadType.h>
+#include <ccnx/common/ccnx_InterestReturn.h>
+
+static bool
+_translateWirePayloadTypeToCCNxPayloadType(CCNxCodecSchemaV1Types_PayloadType wireFormatType, CCNxPayloadType *payloadTypePtr)
+{
+ bool success = true;
+ switch (wireFormatType) {
+ case CCNxCodecSchemaV1Types_PayloadType_Data:
+ *payloadTypePtr = CCNxPayloadType_DATA;
+ break;
+
+ case CCNxCodecSchemaV1Types_PayloadType_Key:
+ *payloadTypePtr = CCNxPayloadType_KEY;
+ break;
+
+ case CCNxCodecSchemaV1Types_PayloadType_Link:
+ *payloadTypePtr = CCNxPayloadType_LINK;
+ break;
+
+ default:
+ // unknown type
+ success = false;
+ }
+ return success;
+}
+
+/**
+ * Translates the wire format value for the PayloadType to CCNxPayloadType
+ */
+static bool
+_decodePayloadType(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t length)
+{
+ CCNxPayloadType payloadType;
+
+ uint64_t wireFormatVarInt;
+ bool success = ccnxCodecTlvDecoder_GetVarInt(decoder, length, &wireFormatVarInt);
+ if (success) {
+ CCNxCodecSchemaV1Types_PayloadType wireFormatType = (CCNxCodecSchemaV1Types_PayloadType) wireFormatVarInt;
+
+ success = _translateWirePayloadTypeToCCNxPayloadType(wireFormatType, &payloadType);
+ }
+
+ if (success) {
+ success = ccnxTlvDictionary_PutInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE, payloadType);
+ }
+
+ return success;
+}
+
+static bool
+_decodeType(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length)
+{
+ bool success = false;
+ switch (type) {
+ case CCNxCodecSchemaV1Types_CCNxMessage_Name:
+ success = ccnxCodecTlvUtilities_PutAsName(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME);
+ break;
+
+ case CCNxCodecSchemaV1Types_CCNxMessage_Payload:
+ success = ccnxCodecTlvUtilities_PutAsBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD);
+ break;
+
+ case CCNxCodecSchemaV1Types_CCNxMessage_KeyIdRestriction:
+ success = ccnxCodecTlvUtilities_PutAsHash(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION);
+ break;
+
+ case CCNxCodecSchemaV1Types_CCNxMessage_ContentObjectHashRestriction:
+ success = ccnxCodecTlvUtilities_PutAsHash(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION);
+ break;
+
+ case CCNxCodecSchemaV1Types_CCNxMessage_PayloadType:
+ success = _decodePayloadType(decoder, packetDictionary, length);
+ break;
+
+ case CCNxCodecSchemaV1Types_CCNxMessage_ExpiryTime:
+ success = ccnxCodecTlvUtilities_PutAsInteger(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME);
+ break;
+
+ case CCNxCodecSchemaV1Types_CCNxMessage_EndChunkNumber:
+ success = ccnxCodecTlvUtilities_PutAsInteger(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT);
+ break;
+
+ default:
+ // if we do not know the TLV type, put it in this container's unknown list
+ success = ccnxCodecTlvUtilities_PutAsListBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_Lists_MESSAGE_LIST);
+ break;
+ }
+
+ if (!success) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+
+ return success;
+}
+
+/*
+ * We are given a decoder that points to the first TLV of a list of TLVs. We keep walking the
+ * list until we come to the end of the decoder.
+ */
+bool
+ccnxCodecSchemaV1MessageDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary)
+{
+ return ccnxCodecTlvUtilities_DecodeContainer(decoder, packetDictionary, _decodeType);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.h
new file mode 100755
index 00000000..30a998aa
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.h
@@ -0,0 +1,57 @@
+/*
+ * 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 ccnxCodecSchemaV1_MessageDecoder.h
+ * @brief <#Brief Description#>
+ *
+ * Decodes the CCNx message body for an Interest or a ContentObject.
+ *
+ * The current CPI Control packet does not use the MessageDecoder or MessageEncoder. It is handled
+ * entirely in the Packet{De,En}coder.
+ *
+ */
+
+#ifndef TransportRTA_ccnxCodecSchemaV1_MessageDecoder_h
+#define TransportRTA_ccnxCodecSchemaV1_MessageDecoder_h
+
+#include <stdbool.h>
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+
+/**
+ * The decode a V1 message, maybe any message type
+ *
+ * The decoder should point to byte 0 of the message TLV
+ * The results are put in the provided dictionary.
+ * It is an error if the message does not extend to the end of
+ * the decoder.
+ *
+ * @param [in] decoder The decoder to parse
+ * @param [in] contentObjectDictionary The results go directly in to the provided dictionary.
+ *
+ * @return true Fully parsed interest, no errors
+ * @return false Error decoding, decoder is left pointing to the first byte of the error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1MessageDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *contentObjectDictionary);
+
+
+#endif // TransportRTA_ccnxCodecSchemaV1_MessageDecoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c
new file mode 100755
index 00000000..7aa14627
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <LongBow/runtime.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/ccnx_PayloadType.h>
+#include <ccnx/common/ccnx_InterestReturn.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+
+#include <ccnx/common/ccnx_Manifest.h>
+#include <ccnx/common/ccnx_ManifestHashGroup.h>
+
+static ssize_t
+_encodeName(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = -1;
+ CCNxName *name = ccnxTlvDictionary_GetName(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME);
+ if (name != NULL) {
+ length = ccnxCodecSchemaV1NameCodec_Encode(encoder, CCNxCodecSchemaV1Types_CCNxMessage_Name, name);
+ }
+
+ // required field for everything except CCNxContentObjects
+ if (!ccnxTlvDictionary_IsContentObject(packetDictionary) && length < 0) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_MISSING_MANDATORY, __func__, __LINE__, ccnxCodecTlvEncoder_Position(encoder));
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+ } else if (ccnxTlvDictionary_IsContentObject(packetDictionary) && name == NULL) {
+ length = 0;
+ }
+
+ return length;
+}
+
+static ssize_t
+_encodeJsonPayload(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCJSON *json = ccnxTlvDictionary_GetJson(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD);
+ if (json != NULL) {
+ char *jsonString = parcJSON_ToCompactString(json);
+ size_t len = strlen(jsonString);
+ length = ccnxCodecTlvEncoder_AppendArray(encoder, CCNxCodecSchemaV1Types_CCNxMessage_Payload, len, (uint8_t *) jsonString);
+ }
+ return length;
+}
+
+static ssize_t
+_encodePayload(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD);
+ if (buffer != NULL) {
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_Payload, buffer);
+ }
+ return length;
+}
+
+static ssize_t
+_encodePayloadType(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE)) {
+ CCNxPayloadType payloadType = (CCNxPayloadType) ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE);
+
+ CCNxCodecSchemaV1Types_PayloadType wireFormatType = CCNxCodecSchemaV1Types_PayloadType_Data;
+
+ switch (payloadType) {
+ case CCNxPayloadType_KEY:
+ wireFormatType = CCNxCodecSchemaV1Types_PayloadType_Key;
+ break;
+
+ case CCNxPayloadType_LINK:
+ wireFormatType = CCNxCodecSchemaV1Types_PayloadType_Link;
+ break;
+
+ default:
+ // anything else is encoded as DATA
+ break;
+ }
+
+ length = ccnxCodecTlvEncoder_AppendUint8(encoder, CCNxCodecSchemaV1Types_CCNxMessage_PayloadType, wireFormatType);
+ } else if (ccnxTlvDictionary_IsValueBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE)) {
+ PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE);
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_PayloadType, buffer);
+ }
+
+ return length;
+}
+
+static ssize_t
+_encodeExpiryTime(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME)) {
+ uint64_t millis = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME);
+ length = ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_CCNxMessage_ExpiryTime, millis);
+ } else if (ccnxTlvDictionary_IsValueBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME)) {
+ PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME);
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_ExpiryTime, buffer);
+ }
+
+ return length;
+}
+
+static ssize_t
+_encodeEndChunkNumber(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT)) {
+ uint64_t endChunkId = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT);
+ length = ccnxCodecTlvEncoder_AppendVarInt(encoder, CCNxCodecSchemaV1Types_CCNxMessage_EndChunkNumber, endChunkId);
+ } else {
+ PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT);
+ if (buffer != NULL) {
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_EndChunkNumber, buffer);
+ }
+ }
+ return length;
+}
+
+static ssize_t
+_encodeKeyIdRestriction(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCCryptoHash *hash = ccnxTlvDictionary_GetObject(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION);
+ if (hash != NULL) {
+ size_t startPosition = ccnxCodecTlvEncoder_Position(encoder);
+ ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_KeyIdRestriction, 0);
+ length = ccnxCodecSchemaV1HashCodec_Encode(encoder, hash);
+ if (length < 0) {
+ return length;
+ }
+
+ ccnxCodecTlvEncoder_SetContainerLength(encoder, startPosition, length);
+ length += 4; // this accounts for the TL fields
+ }
+ return length;
+}
+
+static ssize_t
+_encodeContentObjectHashRestriction(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCCryptoHash *hash = ccnxTlvDictionary_GetObject(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION);
+ if (hash != NULL) {
+ size_t startPosition = ccnxCodecTlvEncoder_Position(encoder);
+ ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_CCNxMessage_ContentObjectHashRestriction, 0);
+ length = ccnxCodecSchemaV1HashCodec_Encode(encoder, hash);
+ if (length < 0) {
+ return length;
+ }
+
+ ccnxCodecTlvEncoder_SetContainerLength(encoder, startPosition, length);
+ length += 4; // this accounts for the TL fields
+ }
+ return length;
+}
+
+
+static ssize_t
+_encodeContentObject(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ ssize_t result;
+
+ result = _encodeName(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodePayloadType(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodeExpiryTime(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodeEndChunkNumber(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodePayload(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ return length;
+}
+
+static ssize_t
+_encodeInterest(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ ssize_t result;
+
+ result = _encodeName(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodeKeyIdRestriction(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodeContentObjectHashRestriction(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodePayload(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ return length;
+}
+
+static ssize_t
+_encodeControl(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ ssize_t result;
+
+ result = _encodeName(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodeJsonPayload(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ return length;
+}
+
+static ssize_t
+_encodeManifest(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ ssize_t result;
+
+ result = _encodeName(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = ccnxCodecSchemaV1ManifestEncoder_Encode(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ return length;
+}
+
+ssize_t
+ccnxCodecSchemaV1MessageEncoder_Encode(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ assertNotNull(encoder, "Parameter encoder must be non-null");
+ assertNotNull(packetDictionary, "Parameter packetDictionary must be non-null");
+
+ ssize_t length = -1;
+
+ if (ccnxTlvDictionary_IsInterest(packetDictionary)) {
+ length = _encodeInterest(encoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsInterestReturn(packetDictionary)) {
+ length = _encodeInterest(encoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsContentObject(packetDictionary)) {
+ length = _encodeContentObject(encoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsControl(packetDictionary)) {
+ length = _encodeControl(encoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsManifest(packetDictionary)) {
+ length = _encodeManifest(encoder, packetDictionary);
+ } else {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETTYPE, __func__, __LINE__, ccnxCodecTlvEncoder_Position(encoder));
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+ length = -1;
+ }
+
+
+ if (length >= 0) {
+ // Put custom fields all last
+ ssize_t customLength = ccnxCodecTlvUtilities_EncodeCustomList(encoder, packetDictionary, CCNxCodecSchemaV1TlvDictionary_Lists_MESSAGE_LIST);
+ if (customLength < 0) {
+ return customLength;
+ }
+ length += customLength;
+ }
+
+ return length;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.h
new file mode 100755
index 00000000..d49417fb
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.h
@@ -0,0 +1,47 @@
+/*
+ * 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 ccnxCodecSchemaV1_MessageEncoder.h
+ * @brief Encode the list of optional headers
+ *
+ */
+
+#ifndef TransportRTA_ccnxCodecSchemaV1_MessageEncoder_h
+#define TransportRTA_ccnxCodecSchemaV1_MessageEncoder_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+#include <parc/security/parc_Signer.h>
+
+/**
+ * Encodes the body of the CCNxMessage
+ *
+ * Encodes an Interest, ContentObject, or Control message
+ *
+ * @param [in] encoder Appends the CCNx message to the encoder
+ * @param [in] packetDictionary The fields to encode
+ *
+ * @return non-negative Total bytes appended to encoder
+ * @return -1 An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+ssize_t ccnxCodecSchemaV1MessageEncoder_Encode(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary);
+
+#endif // TransportRTA_ccnxCodecSchemaV1_MessageEncoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.c
new file mode 100755
index 00000000..a769477f
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.c
@@ -0,0 +1,85 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.h>
+
+size_t
+ccnxCodecSchemaV1NameCodec_Encode(CCNxCodecTlvEncoder *encoder, uint16_t type, const CCNxName *name)
+{
+ assertNotNull(encoder, "Parameter encoder must be non-null");
+ assertNotNull(name, "Parameter name must be non-null");
+
+ size_t containerPosition = ccnxCodecTlvEncoder_Position(encoder);
+ size_t containerLength = ccnxCodecTlvEncoder_AppendContainer(encoder, type, 0);
+
+ size_t segmentCount = ccnxName_GetSegmentCount(name);
+ size_t innerLength = 0;
+ for (int i = 0; i < segmentCount; i++) {
+ CCNxNameSegment *segment = ccnxName_GetSegment(name, i);
+ innerLength += ccnxCodecSchemaV1NameSegmentCodec_Encode(encoder, segment);
+ }
+
+ // now go back and fixup the container's length
+ ccnxCodecTlvEncoder_SetContainerLength(encoder, containerPosition, innerLength);
+
+ return containerLength + innerLength;
+}
+
+CCNxName *
+ccnxCodecSchemaV1NameCodec_Decode(CCNxCodecTlvDecoder *decoder, uint16_t type)
+{
+ CCNxName *name = NULL;
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, 4)) {
+ uint16_t tlvtype = ccnxCodecTlvDecoder_PeekType(decoder);
+ if (tlvtype == type) {
+ // call just for the side-effect of advancing the buffer
+ (void) ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ name = ccnxCodecSchemaV1NameCodec_DecodeValue(decoder, length);
+ }
+ }
+
+ return name;
+}
+
+CCNxName *
+ccnxCodecSchemaV1NameCodec_DecodeValue(CCNxCodecTlvDecoder *decoder, uint16_t length)
+{
+ CCNxName *name = NULL;
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, length)) {
+ name = ccnxName_Create();
+ size_t nameEnd = ccnxCodecTlvDecoder_Position(decoder) + length;
+
+ while (ccnxCodecTlvDecoder_Position(decoder) < nameEnd) {
+ CCNxNameSegment *segment = ccnxCodecSchemaV1NameSegmentCodec_Decode(decoder);
+ ccnxName_Append(name, segment);
+ ccnxNameSegment_Release(&segment);
+ }
+ }
+ return name;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h
new file mode 100755
index 00000000..6c3298a2
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h
@@ -0,0 +1,83 @@
+/*
+ * 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 ccnxCodecSchemaV1_NameCodec.h
+ * @brief TLV codec for CCNx types
+ *
+ * <#Detailed Description#>
+ *
+ */
+
+#ifndef CCNxCodecSchemaV1_NameCodec_h
+#define CCNxCodecSchemaV1_NameCodec_h
+
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+#include <ccnx/common/ccnx_Name.h>
+
+/**
+ * Encodes the name to the TLV Encoder
+ *
+ * Will append the Name after the current encoder location
+ *
+ * @param [in] type The TLV type to use for the Name container
+ *
+ * @return bytes The number of bytes appended to the encoder
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+size_t ccnxCodecSchemaV1NameCodec_Encode(CCNxCodecTlvEncoder *encoder, uint16_t type, const CCNxName *name);
+
+/**
+ * Decode the buffer as a CCNxName beginning at the current position
+ *
+ * The buffer must be pointing to the beginnig of the "type". The decoder will
+ * verify that the type matches `type'. If it does not match, it will return NULL.
+ *
+ * @param [in] decoder The decoder
+ * @param [in] type The TLV type that the decoder should currently be pointing at
+ *
+ * @return non-null The CCNxName decoded
+ * @return null An error: either type did not match or some other error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+CCNxName *ccnxCodecSchemaV1NameCodec_Decode(CCNxCodecTlvDecoder *decoder, uint16_t type);
+
+/**
+ * The decoder points to the first byte of the Name "value"
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] decoder The Tlv Decoder pointing to the start of the Name value
+ * @param [in] length the length of the Name value
+ *
+ * @return non-null A parsed name
+ * @return null An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+CCNxName *ccnxCodecSchemaV1NameCodec_DecodeValue(CCNxCodecTlvDecoder *decoder, uint16_t length);
+#endif // CCNxCodecSchemaV1_NameCodec_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.c
new file mode 100755
index 00000000..55d02bab
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.c
@@ -0,0 +1,59 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.h>
+
+size_t
+ccnxCodecSchemaV1NameSegmentCodec_Encode(CCNxCodecTlvEncoder *encoder, CCNxNameSegment *segment)
+{
+ assertTrue(ccnxNameSegment_Length(segment) <= UINT16_MAX,
+ "Name segment too long! length %zu maximum %u",
+ ccnxNameSegment_Length(segment),
+ UINT16_MAX);
+
+ uint16_t segment_type = ccnxNameSegment_GetType(segment);
+ PARCBuffer *value = ccnxNameSegment_GetValue(segment);
+
+ return ccnxCodecTlvEncoder_AppendBuffer(encoder, segment_type, value);
+}
+
+CCNxNameSegment *
+ccnxCodecSchemaV1NameSegmentCodec_Decode(CCNxCodecTlvDecoder *decoder)
+{
+ CCNxNameSegment *segment = NULL;
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, 4)) {
+ uint16_t type = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, length)) {
+ PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(decoder, length);
+ segment = ccnxNameSegment_CreateTypeValue(type, value);
+ parcBuffer_Release(&value);
+ }
+ }
+
+ return segment;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.h
new file mode 100755
index 00000000..c6797cff
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameSegmentCodec.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.
+ */
+
+/**
+ * @file ccnxCodecSchemaV1_NameSegmentCodec.h
+ * @brief TLV codec for CCNx types
+ *
+ * Encode/decode a CCNx name segment using the V1 schema
+ *
+ */
+
+#ifndef CCNxCodecSchemaV1_NameSegmentCodec_h
+#define CCNxCodecSchemaV1_NameSegmentCodec_h
+
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+#include <ccnx/common/ccnx_Name.h>
+
+/**
+ * Encodes the name segment using the segment type as the TLV type
+ *
+ * Appends the name segment to the encoder. The TLV type is implicit in
+ * the CCNxNameSegment.
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return number The number of bytes appended, including the type and length.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+size_t ccnxCodecSchemaV1NameSegmentCodec_Encode(CCNxCodecTlvEncoder *encoder, CCNxNameSegment *segment);
+
+/**
+ * Decodes the current location of the decoder as a CCNxNameSegment
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] decoder The decoder object
+ *
+ * @return non-null A CCNxNameSement
+ * @return null An error, such as buffer underrun
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+CCNxNameSegment *ccnxCodecSchemaV1NameSegmentCodec_Decode(CCNxCodecTlvDecoder *decoder);
+#endif // CCNxCodecSchemaV1_NameSegmentCodec_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.c
new file mode 100755
index 00000000..48554b9a
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.c
@@ -0,0 +1,125 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+
+static bool
+_decodeType(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length)
+{
+ bool success = false;
+ switch (type) {
+ case CCNxCodecSchemaV1Types_OptionalHeaders_InterestFragment:
+ success = ccnxCodecTlvUtilities_PutAsBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG);
+ break;
+
+ case CCNxCodecSchemaV1Types_OptionalHeaders_ContentObjectFragment:
+ success = ccnxCodecTlvUtilities_PutAsBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_OBJFRAG);
+ break;
+
+ case CCNxCodecSchemaV1Types_OptionalHeaders_InterestLifetime:
+ // its a time, so use an Integer
+ success = ccnxCodecTlvUtilities_PutAsInteger(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime);
+ break;
+
+ case CCNxCodecSchemaV1Types_OptionalHeaders_RecommendedCacheTime:
+ // its a time, so use an Integer
+ success = ccnxCodecTlvUtilities_PutAsInteger(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime);
+ break;
+ case CCNxCodecSchemaV1Types_OptionalHeaders_PathLabel:
+ success = ccnxCodecTlvUtilities_PutAsInteger(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel);
+ break;
+
+ default: {
+ // if we do not know the TLV type, put it in this container's unknown list
+ success = ccnxCodecTlvUtilities_PutAsListBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_Lists_HEADERS);
+ }
+ break;
+ }
+ if (!success) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+ return success;
+}
+
+/*
+ * We are given a decoder that points to the first TLV of a list of TLVs. We keep walking the
+ * list until we come to the end of the decoder.
+ */
+bool
+ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary)
+{
+ return ccnxCodecTlvUtilities_DecodeContainer(decoder, packetDictionary, _decodeType);
+}
+
+// ==== Getters
+
+PARCBuffer *
+ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestFragmentHeader(CCNxTlvDictionary *packetDictionary)
+{
+ PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG);
+ return buffer;
+}
+
+PARCBuffer *
+ccnxCodecSchemaV1OptionalHeadersDecoder_GetContentObjectFragmentHeader(CCNxTlvDictionary *packetDictionary)
+{
+ PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_OBJFRAG);
+ return buffer;
+}
+
+uint64_t
+ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestLifetimeHeader(CCNxTlvDictionary *packetDictionary)
+{
+ uint64_t lifetime = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime);
+ return lifetime;
+}
+
+uint64_t
+ccnxCodecSchemaV1OptionalHeadersDecoder_GetRecommendedCacheTimeHeader(CCNxTlvDictionary *packetDictionary)
+{
+ uint64_t cachetime = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime);
+ return cachetime;
+}
+
+uint64_t
+ccnxCodecSchemaV1OptionalHeadersDecoder_GetPathLabel(CCNxTlvDictionary *packetDictionary)
+{
+ uint64_t pathLabel = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel);
+ return pathLabel;
+}
+
+PARCBuffer *
+ccnxCodecSchemaV1OptionalHeadersDecoder_GetCustomType(CCNxTlvDictionary *packetDictionary, uint32_t key)
+{
+ PARCBuffer *buffer = ccnxTlvDictionary_ListGetByType(packetDictionary, CCNxCodecSchemaV1TlvDictionary_Lists_HEADERS, key);
+ return buffer;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.h
new file mode 100755
index 00000000..94463ad1
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.h
@@ -0,0 +1,144 @@
+/*
+ * 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 ccnxCodecSchemaV1_OptionalHeadersDecoder.h
+ * @brief Decode the list of optional headers
+ *
+ * A reference to each optional header will be stored in the provided CCNxTlvDictionary.
+ *
+ */
+
+#ifndef TransportRTA_ccnxCodecSchemaV1_OptionalHeadersDecoder_h
+#define TransportRTA_ccnxCodecSchemaV1_OptionalHeadersDecoder_h
+
+#include <stdbool.h>
+
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+
+/**
+ * The decode a list of Version 1 optional headers
+ *
+ * The decoder should point to the first byte of the first optional header.
+ * The decoder will advance until the end of the buffer.
+ * It is an error for the last optional header to either go beyond the end of the
+ * decoder or for it to underrun the end of the decoder. It must exactly align.
+ *
+ * @param [in] decoder The decoder to parse
+ * @param [in] packetDictionary The results go directly in to the provided dictionary.
+ *
+ * @return true Fully parsed interest, no errors
+ * @return false Error decoding, decoder is left pointing to the first byte of the error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the Interest Fragment header buffer
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] packetDictionary The packet dictionary
+ *
+ * @return non-null The header buffer
+ * @return null The header does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+PARCBuffer *ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestFragmentHeader(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the Content Object Fragment header buffer
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] packetDictionary The packet dictionary
+ *
+ * @return non-null The header buffer
+ * @return null The header does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+PARCBuffer *ccnxCodecSchemaV1OptionalHeadersDecoder_GetContentObjectFragmentHeader(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the Interest Lifetime header value
+ *
+ * Returns the byte array of the Interest Lifetime, which is encoded as a uint64_t milli-seconds
+ * since the UTC epoch. The PARCBuffer returned wraps the underlying memory so any changes to the
+ * buffer will be reflected in the header.
+ *
+ * @param [in] packetDictionary The packet dictionary
+ *
+ * @return number The Interest Lifetime
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+uint64_t ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestLifetimeHeader(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * A convenience function to return the Recommended Cache Time (RCT) header
+ *
+ * Returns the byte array of the RCT, which is encoded as a uint64_t milli-seconds
+ * since the UTC epoch. The PARCBuffer returned wraps the underlying memory so any changes to the
+ * buffer will be reflected in the header.
+ *
+ * @param [in] packetDictionary The packet dictionary
+ *
+ * @return number The Recommended Cache Time
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+uint64_t ccnxCodecSchemaV1OptionalHeadersDecoder_GetRecommendedCacheTimeHeader(CCNxTlvDictionary *packetDictionary);
+
+uint64_t ccnxCodecSchemaV1OptionalHeadersDecoder_GetRecommendedPathLabel(CCNxTlvDictionary *packetDictionary);
+
+/**
+ * Retrieves a TLV header that is not part of the V1 schema spec
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return non-NULL The header
+ * @return NULL The header field does not exist
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+PARCBuffer *ccnxCodecSchemaV1OptionalHeadersDecoder_GetCustomType(CCNxTlvDictionary *packetDictionary, uint32_t key);
+
+#endif // TransportRTA_ccnxCodecSchemaV1_OptionalHeadersDecoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.c
new file mode 100755
index 00000000..f108a1c3
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.c
@@ -0,0 +1,187 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+
+static ssize_t
+_EncodeInterestLifetime(CCNxCodecTlvEncoder *optionalHeadersEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+
+ // allow either encoding as an Integer or as a Buffer
+
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime)) {
+ uint64_t lifetime = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime);
+ length = ccnxCodecTlvEncoder_AppendVarInt(optionalHeadersEncoder, CCNxCodecSchemaV1Types_OptionalHeaders_InterestLifetime, lifetime);
+ } else if (ccnxTlvDictionary_IsValueBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime)) {
+ PARCBuffer *lifetime = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime);
+ length = ccnxCodecTlvEncoder_AppendBuffer(optionalHeadersEncoder, CCNxCodecSchemaV1Types_OptionalHeaders_InterestLifetime, lifetime);
+ }
+
+ return length;
+}
+
+static ssize_t
+_EncodeRecommendedCacheTime(CCNxCodecTlvEncoder *optionalHeadersEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+
+ // allow either encoding as an Integer or as a Buffer
+
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime)) {
+ uint64_t cacheTime = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime);
+ length = ccnxCodecTlvEncoder_AppendVarInt(optionalHeadersEncoder, CCNxCodecSchemaV1Types_OptionalHeaders_RecommendedCacheTime, cacheTime);
+ } else if (ccnxTlvDictionary_IsValueBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime)) {
+ PARCBuffer *cacheTime = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime);
+ length = ccnxCodecTlvEncoder_AppendBuffer(optionalHeadersEncoder, CCNxCodecSchemaV1Types_OptionalHeaders_RecommendedCacheTime, cacheTime);
+ }
+
+ return length;
+}
+
+static ssize_t
+_EncodePathLabel(CCNxCodecTlvEncoder *optionalHeadersEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel)) {
+ uint16_t pathLabel = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel);
+ length = ccnxCodecTlvEncoder_AppendVarInt(optionalHeadersEncoder, CCNxCodecSchemaV1Types_OptionalHeaders_PathLabel, pathLabel);
+ } else if (ccnxTlvDictionary_IsValueBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel)) {
+ PARCBuffer *pathLabel = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel);
+ length = ccnxCodecTlvEncoder_AppendBuffer(optionalHeadersEncoder, CCNxCodecSchemaV1Types_OptionalHeaders_PathLabel, pathLabel);
+ }
+
+ return length;
+}
+
+static ssize_t
+_EncodeInterestFrag(CCNxCodecTlvEncoder *optionalHeadersEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG);
+ if (buffer != NULL) {
+ length = ccnxCodecTlvEncoder_AppendBuffer(optionalHeadersEncoder, CCNxCodecSchemaV1Types_OptionalHeaders_InterestFragment, buffer);
+ }
+ return length;
+}
+
+static ssize_t
+_EncodeContentObjectFrag(CCNxCodecTlvEncoder *optionalHeadersEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCBuffer *buffer = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_OBJFRAG);
+ if (buffer != NULL) {
+ length = ccnxCodecTlvEncoder_AppendBuffer(optionalHeadersEncoder, CCNxCodecSchemaV1Types_OptionalHeaders_ContentObjectFragment, buffer);
+ }
+ return length;
+}
+
+static ssize_t
+_EncodeInterestHeaders(CCNxCodecTlvEncoder *optionalHeadersEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ ssize_t intFragLength = _EncodeInterestFrag(optionalHeadersEncoder, packetDictionary);
+ if (intFragLength < 0) {
+ return intFragLength;
+ }
+ length += intFragLength;
+
+ ssize_t intLifeLength = _EncodeInterestLifetime(optionalHeadersEncoder, packetDictionary);
+ if (intLifeLength < 0) {
+ return intLifeLength;
+ }
+ length += intLifeLength;
+
+ ssize_t customLength = ccnxCodecTlvUtilities_EncodeCustomList(optionalHeadersEncoder, packetDictionary, CCNxCodecSchemaV1TlvDictionary_Lists_HEADERS);
+ if (customLength < 0) {
+ return customLength;
+ }
+ length += customLength;
+
+ return length;
+}
+
+static ssize_t
+_EncodeContentObjectHeaders(CCNxCodecTlvEncoder *optionalHeadersEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ ssize_t result;
+
+ result = _EncodeContentObjectFrag(optionalHeadersEncoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _EncodeRecommendedCacheTime(optionalHeadersEncoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _EncodePathLabel(optionalHeadersEncoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = ccnxCodecTlvUtilities_EncodeCustomList(optionalHeadersEncoder, packetDictionary, CCNxCodecSchemaV1TlvDictionary_Lists_HEADERS);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ return length;
+}
+
+
+ssize_t
+ccnxCodecSchemaV1OptionalHeadersEncoder_Encode(CCNxCodecTlvEncoder *optionalHeadersEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ assertNotNull(optionalHeadersEncoder, "Parameter optionalHeadersEncoder must be non-null");
+ assertNotNull(packetDictionary, "Parameter packetDictionary must be non-null");
+
+ ssize_t result = 0;
+ if (ccnxTlvDictionary_IsInterest(packetDictionary) || ccnxTlvDictionary_IsInterestReturn(packetDictionary)) {
+ result = _EncodeInterestHeaders(optionalHeadersEncoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsContentObject(packetDictionary) || ccnxTlvDictionary_IsManifest(packetDictionary)) {
+ result = _EncodeContentObjectHeaders(optionalHeadersEncoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsControl(packetDictionary)) {
+ result = ccnxCodecTlvUtilities_EncodeCustomList(optionalHeadersEncoder, packetDictionary, CCNxCodecSchemaV1TlvDictionary_Lists_HEADERS);
+ } else {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETTYPE, __func__, __LINE__, ccnxCodecTlvEncoder_Position(optionalHeadersEncoder));
+ ccnxCodecTlvEncoder_SetError(optionalHeadersEncoder, error);
+ ccnxCodecError_Release(&error);
+ result = -1;
+ }
+
+ return result;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.h
new file mode 100755
index 00000000..3f7632ca
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.h
@@ -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.
+ */
+
+/**
+ * @file ccnxCodecSchemaV1_OptionalHeadersEncoder.h
+ * @brief Encode the list of optional headers
+ *
+ */
+
+#ifndef TransportRTA_ccnxCodecSchemaV1_OptionalHeadersEncoder_h
+#define TransportRTA_ccnxCodecSchemaV1_OptionalHeadersEncoder_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+
+/**
+ * Appends the Optional Headers to the encoderder
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [in] encoder An allocated encoder to append to
+ * @param [in] packetDictionary The dictionary containing the optional headers
+ *
+ * @return non-negative Total bytes appended to encoder
+ * @return -1 An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+ssize_t ccnxCodecSchemaV1OptionalHeadersEncoder_Encode(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary);
+
+#endif // TransportRTA_ccnxCodecSchemaV1_OptionalHeadersEncoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.c
new file mode 100644
index 00000000..692b3291
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.c
@@ -0,0 +1,289 @@
+/*
+ * 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 <sys/time.h>
+
+#include <LongBow/runtime.h>
+#include <parc/algol/parc_Memory.h>
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+#include <ccnx/common/internal/ccnx_WireFormatFacadeV1.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ManifestDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.h>
+
+typedef struct rta_tlv_schema_v1_data {
+ CCNxCodecTlvDecoder *decoder;
+ CCNxTlvDictionary *packetDictionary;
+} _CCNxCodecSchemaV1Data;
+
+/**
+ * Decodes the per-hop optional headers
+ *
+ * @param [in] data The packet decoder state
+ *
+ * @return true successful decode
+ * @return false A decoding error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static bool
+_decodeOptionalHeaders(_CCNxCodecSchemaV1Data *data)
+{
+ size_t optionalHeaderLength = ccnxCodecSchemaV1FixedHeaderDecoder_GetOptionalHeaderLength(data->packetDictionary);
+ CCNxCodecTlvDecoder *optionalHeaderDecoder = ccnxCodecTlvDecoder_GetContainer(data->decoder, optionalHeaderLength);
+
+ bool success = ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(optionalHeaderDecoder, data->packetDictionary);
+
+ ccnxCodecTlvDecoder_Destroy(&optionalHeaderDecoder);
+ return success;
+}
+
+/**
+ * Decodes the "value" of the CPI "TLV"
+ *
+ * the CPI packet is encoded as a single TLV container of type 0xBEEF (detected in _decodeMessage).
+ * At this point, the cpiDecoder wraps the CPI payload, which is the encapsulated JSON
+ *
+ * @param [in] cpiDecoder Decoder wrapping the value
+ * @param [in] packetDictionary where to place the results
+ *
+ * @retval true Good decode
+ * @retval false An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static bool
+_decodeCPI(CCNxCodecTlvDecoder *cpiDecoder, CCNxTlvDictionary *packetDictionary)
+{
+ // we just take the whole contents of the decoder and put in the the PAYLOAD dictionary entry.
+ size_t length = ccnxCodecTlvDecoder_Remaining(cpiDecoder);
+ PARCBuffer *payload = ccnxCodecTlvDecoder_GetValue(cpiDecoder, length);
+
+ PARCJSON *json = parcJSON_ParseBuffer(payload);
+
+ bool success = ccnxTlvDictionary_PutJson(packetDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, json);
+ parcJSON_Release(&json);
+ parcBuffer_Release(&payload);
+ return success;
+}
+
+/**
+ * Decodes the CCNx message inside a TLV packet
+ *
+ * Creates an inner decoder that slices the decode buffer then passes that and our
+ * message dictionary to the appropriate inner decoder.
+ *
+ * @param [in] data The packet decoder state
+ *
+ * @return true successful decode
+ * @return false A decoding error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static bool
+_decodeMessage(_CCNxCodecSchemaV1Data *data)
+{
+ bool success = false;
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, 4)) {
+ // what kind of message are we looking at?
+ // Note that this is based on the TLV container, not the fixed head PacketType
+ uint16_t tlv_type = ccnxCodecTlvDecoder_GetType(data->decoder);
+ uint16_t tlv_length = ccnxCodecTlvDecoder_GetLength(data->decoder);
+
+ // ensure its a proper tlv type
+ switch (tlv_type) {
+ case CCNxCodecSchemaV1Types_MessageType_Interest: // fallthrough
+ case CCNxCodecSchemaV1Types_MessageType_ContentObject: // fallthrough
+ case CCNxCodecSchemaV1Types_MessageType_Control: // fallthrough
+ case CCNxCodecSchemaV1Types_MessageType_Manifest: // fallthrough
+ break;
+
+ default:
+ return false;
+ }
+
+ // cross check with the fixed header value
+ // ccnxCodecSchemaV1FixedHeaderDecoder_Decode ensures that PacketLength is not less than HeaderLength
+ size_t messageLength = ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength(data->packetDictionary) - ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength(data->packetDictionary);
+
+ if (tlv_length <= messageLength && ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, tlv_length)) {
+ // This decode is for the "value" of the message, it does not include the wrapper
+ CCNxCodecTlvDecoder *messageDecoder = ccnxCodecTlvDecoder_GetContainer(data->decoder, tlv_length);
+
+ if (tlv_type == CCNxCodecSchemaV1Types_MessageType_Control) {
+ // the CPI messages are not a proper "message" in that there's no inner TLV, its just data
+ success = _decodeCPI(messageDecoder, data->packetDictionary);
+ } else if (tlv_type == CCNxCodecSchemaV1Types_MessageType_Manifest) {
+ ccnxTlvDictionary_SetMessageType_Manifest(data->packetDictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ success = ccnxCodecSchemaV1ManifestDecoder_Decode(messageDecoder, data->packetDictionary);
+ } else {
+ success = ccnxCodecSchemaV1MessageDecoder_Decode(messageDecoder, data->packetDictionary);
+ }
+
+ ccnxCodecTlvDecoder_Destroy(&messageDecoder);
+ } else {
+ // raise an error
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_TOO_LONG, __func__, __LINE__, ccnxCodecTlvDecoder_Position(data->decoder));
+ ccnxCodecTlvDecoder_SetError(data->decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+ }
+
+ return success;
+}
+
+static bool
+_decodeValidationAlg(_CCNxCodecSchemaV1Data *data)
+{
+ bool success = false;
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, 4)) {
+ // what kind of message are we looking at?
+ // Note that this is based on the TLV container, not the fixed head PacketType
+ uint16_t tlv_type = ccnxCodecTlvDecoder_GetType(data->decoder);
+ uint16_t tlv_length = ccnxCodecTlvDecoder_GetLength(data->decoder);
+
+ if (tlv_type == CCNxCodecSchemaV1Types_MessageType_ValidationAlg &&
+ ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, tlv_length)) {
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_GetContainer(data->decoder, tlv_length);
+
+ success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, data->packetDictionary);
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ } else {
+ // raise and error
+ if (!ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, tlv_length)) {
+ // tlv_length goes beyond the decoder
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_TOO_LONG, __func__, __LINE__, ccnxCodecTlvDecoder_Position(data->decoder));
+ ccnxCodecTlvDecoder_SetError(data->decoder, error);
+ ccnxCodecError_Release(&error);
+ } else {
+ // not CCNxCodecSchemaV1Types_MessageType_ValidationAlg
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(data->decoder));
+ ccnxCodecTlvDecoder_SetError(data->decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+ }
+ }
+
+ return success;
+}
+
+static bool
+_decodeValidationPayload(_CCNxCodecSchemaV1Data *data)
+{
+ bool success = false;
+
+ if (ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, 4)) {
+ // what kind of message are we looking at?
+ // Note that this is based on the TLV container, not the fixed head PacketType
+ uint16_t tlv_type = ccnxCodecTlvDecoder_GetType(data->decoder);
+ uint16_t tlv_length = ccnxCodecTlvDecoder_GetLength(data->decoder);
+
+ if (tlv_type == CCNxCodecSchemaV1Types_MessageType_ValidationPayload &&
+ ccnxCodecTlvDecoder_EnsureRemaining(data->decoder, tlv_length)) {
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_GetContainer(data->decoder, tlv_length);
+
+ success = ccnxCodecSchemaV1ValidationDecoder_DecodePayload(decoder, data->packetDictionary);
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ }
+ }
+
+ return success;
+}
+
+bool
+ccnxCodecSchemaV1PacketDecoder_Decode(CCNxCodecTlvDecoder *packetDecoder, CCNxTlvDictionary *packetDictionary)
+{
+ bool decodeSuccess = false;
+
+ _CCNxCodecSchemaV1Data data;
+
+ // we temporarily store this reference, but we do not destroy it. This
+ // is just to pass the reference down the decode chain, it is not
+ // stored beyond the immediate scope. Therefore, no reference acquired.
+ data.packetDictionary = packetDictionary;
+ data.decoder = packetDecoder;
+
+ if (ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data.decoder, data.packetDictionary)) {
+ if (_decodeOptionalHeaders(&data)) {
+ // Record the position we'd start the signature verification at
+ size_t signatureStartPosition = ccnxCodecTlvDecoder_Position(data.decoder);
+
+
+ // Mark the beginning of the ContentObject hash region.
+ CCNxWireFormatFacadeV1_Implementation.setContentObjectHashRegionStart(data.packetDictionary, signatureStartPosition);
+
+ if (_decodeMessage(&data)) {
+ // If there's anything else left, it must be the validation alg and payload
+ if (!ccnxCodecTlvDecoder_IsEmpty(data.decoder)) {
+ if (_decodeValidationAlg(&data)) {
+ // at this point, we've advanced to the end of the validation algorithm,
+ // that's where we would end signature verification
+ size_t signatureStopPosition = ccnxCodecTlvDecoder_Position(data.decoder);
+
+ CCNxWireFormatFacadeV1_Implementation.setProtectedRegionStart(data.packetDictionary, signatureStartPosition);
+ CCNxWireFormatFacadeV1_Implementation.setProtectedRegionLength(data.packetDictionary, signatureStopPosition - signatureStartPosition);
+
+ if (_decodeValidationPayload(&data)) {
+ decodeSuccess = true;
+ }
+ }
+ } else {
+ // nothing after the message, so that's a successful decode
+ decodeSuccess = true;
+ }
+
+ // Mark the length of the ContentObject hash region (to the end of the packet).
+ size_t contentObjectHashRegionLength = ccnxCodecTlvDecoder_Position(data.decoder) - signatureStartPosition;
+ CCNxWireFormatFacadeV1_Implementation.setContentObjectHashRegionLength(data.packetDictionary, contentObjectHashRegionLength);
+ }
+ }
+ }
+
+ return decodeSuccess;
+}
+
+bool
+ccnxCodecSchemaV1PacketDecoder_BufferDecode(PARCBuffer *packetBuffer, CCNxTlvDictionary *packetDictionary)
+{
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, packetDictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ return success;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.h
new file mode 100755
index 00000000..9c1defd9
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketDecoder.h
@@ -0,0 +1,91 @@
+/*
+ * 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 ccnxCodecSchemaV1_PacketDecoder.h
+ * @brief Decoder for the version 1 TLV Packet
+ *
+ * The Schema version 1 Dictionary is organized in containers: FixedHeader, OptionalHeaders, (Interest, ContentObject, Control), Verification.
+ *
+ * Each container is its own dictionary.
+ *
+ * Example:
+ * @code
+ * {
+ * CCNxTlvDictionary *packetDictionary = ccnxTlvDictionary_Create();
+ * ccnxCodecSchemaV1PacketDecoder_Decode(packetBuffer, packetDictionary);
+ * // the fields in the packetDictionary are now set
+ * }
+ * @endcode
+ *
+ */
+
+#ifndef CCNxCodecSchemaV1_PacketDecoder_h
+#define CCNxCodecSchemaV1_PacketDecoder_h
+
+#include <parc/algol/parc_Buffer.h>
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+
+
+/**
+ * Decode a packet in to a dictionary.
+ *
+ * The buffer should be set at the start of the fixed header. This call is equivalent
+ * to ccnxCodecSchemaV1PacketDecoder_Decode(), except it allocates and destroys a temporary
+ * CCNxCodecTlvDecoder.
+ *
+ * The dictionary will be filled in with all fields available in the packetBuffer.
+ *
+ * Caveat: there is no way to find out where the error was if returned "false"
+ *
+ * @param [in] buffer The packet buffer
+ * @param [in] packetDictionary The dictionary to fill in
+ *
+ * @return true Successful decode
+ * @return false There was an error somewhere
+ *
+ * Example:
+ * @code
+ * {
+ * }
+ * @endcode
+ */
+bool ccnxCodecSchemaV1PacketDecoder_BufferDecode(PARCBuffer *packetBuffer, CCNxTlvDictionary *packetDictionary);
+
+/**
+ * Decode in to in to a dictionary.
+ *
+ * The buffer should be set at the start of the fixed header.
+ *
+ * The dictionary will be filled in with all fields available in the packetDecoder.
+ *
+ * Caveat: there is no way to find out where the error was if returned "false"
+ *
+ * @param [in] buffer The packet buffer
+ * @param [in] packetDictionary The dictionary to fill in
+ *
+ * @return true Successful decode
+ * @return false There was an error somewhere
+ *
+ * Example:
+ * @code
+ * {
+ * }
+ * @endcode
+ */
+bool ccnxCodecSchemaV1PacketDecoder_Decode(CCNxCodecTlvDecoder *packetDecoder, CCNxTlvDictionary *packetDictionary);
+
+#endif // CCNxCodecSchemaV1_PacketDecoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.c
new file mode 100755
index 00000000..bddd32d4
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.c
@@ -0,0 +1,353 @@
+/*
+ * 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 <sys/time.h>
+#include <inttypes.h>
+
+#include <LongBow/runtime.h>
+#include <parc/algol/parc_Memory.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeaderEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_OptionalHeadersEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_MessageEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.h>
+
+#include <ccnx/common/internal/ccnx_InterestDefault.h>
+#include <ccnx/common/internal/ccnx_ValidationFacadeV1.h>
+#include <ccnx/common/internal/ccnx_WireFormatMessageInterface.h>
+
+// =====================================================
+// Private API
+
+static uint8_t
+_getHopLimit(CCNxTlvDictionary *packetDictionary)
+{
+ uint8_t hoplimit = (uint8_t) CCNxInterestDefault_HopLimit;
+
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT)) {
+ hoplimit = (uint8_t) ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT);
+ }
+ return hoplimit;
+}
+
+static uint8_t
+_getInterestReturnCode(CCNxTlvDictionary *packetDictionary)
+{
+ uint8_t returnCode = (uint8_t) 0;
+
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestReturnCode)) {
+ returnCode =
+ (uint8_t) ccnxTlvDictionary_GetInteger(packetDictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestReturnCode);
+ }
+ return returnCode;
+}
+
+/**
+ * Creates a fixed header from the given parameters and encodes in network byte order
+ *
+ * All parameters in host byte order.
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return non-negative The total bytes appended to the encode buffer
+ * @return -1 An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static ssize_t
+_encodeFixedHeader(CCNxCodecTlvEncoder *fixedHeaderEncoder,
+ CCNxTlvDictionary *packetDictionary,
+ int packetType,
+ ssize_t headerLength,
+ ssize_t packetLength)
+{
+ CCNxCodecSchemaV1FixedHeader fixedHeader;
+ memset(&fixedHeader, 0, sizeof(fixedHeader));
+
+ fixedHeader.version = 1;
+ fixedHeader.packetType = packetType;
+ fixedHeader.packetLength = packetLength;
+ fixedHeader.headerLength = headerLength;
+
+ if ((packetType == CCNxCodecSchemaV1Types_PacketType_Interest) ||
+ (packetType == CCNxCodecSchemaV1Types_PacketType_InterestReturn)) {
+ CCNxCodecSchemaV1InterestHeader *interestHeader = (CCNxCodecSchemaV1InterestHeader *) &fixedHeader;
+ interestHeader->hopLimit = _getHopLimit(packetDictionary);
+ if (packetType == CCNxCodecSchemaV1Types_PacketType_InterestReturn) {
+ interestHeader->returnCode = _getInterestReturnCode(packetDictionary);
+ }
+ }
+
+ return ccnxCodecSchemaV1FixedHeaderEncoder_EncodeHeader(fixedHeaderEncoder, &fixedHeader);
+}
+
+static ssize_t
+_encodeOptionalHeaders(CCNxCodecTlvEncoder *optionalHeaderEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ // Optional Headers do not have a container, so just append them right to the buffer
+ size_t optionalHeadersLength = 0;
+ optionalHeadersLength = ccnxCodecSchemaV1OptionalHeadersEncoder_Encode(optionalHeaderEncoder, packetDictionary);
+ return optionalHeadersLength;
+}
+
+/**
+ * CPI payload is simply a dump of the PAYLOAD dictionary entry.
+ *
+ * There are no inner TLVs of this message, so it is not encoded like a normal message
+ * with a call to ccnxCodecSchemaV1MessageEncoder_Encode(). Rather it is written here.
+ *
+ * @param [<#in#> | <#out#> | <#in,out#>] <#name#> <#description#>
+ *
+ * @return non-negative The number of bytes appended to the buffer
+ * @return negative An error
+ *
+ * Example:
+ * @code
+ * {
+ * <#example#>
+ * }
+ * @endcode
+ */
+static ssize_t
+_encodeCPI(CCNxCodecTlvEncoder *cpiEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ // Optional Headers do not have a container, so just append them right to the buffer
+ size_t payloadLength = 0;
+
+ if (ccnxTlvDictionary_IsValueJson(packetDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD)) {
+ PARCJSON *json = ccnxTlvDictionary_GetJson(packetDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD);
+ if (json) {
+ char *jsonString = parcJSON_ToCompactString(json);
+
+ payloadLength = strlen(jsonString);
+ ccnxCodecTlvEncoder_AppendRawArray(cpiEncoder, payloadLength, (uint8_t * ) jsonString);
+ parcMemory_Deallocate((void **) &jsonString);
+ }
+ } else {
+ PARCBuffer *payload = ccnxTlvDictionary_GetBuffer(packetDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD);
+
+ payloadLength = parcBuffer_Remaining(payload);
+ uint8_t *overlay = parcBuffer_Overlay(payload, 0);
+ ccnxCodecTlvEncoder_AppendRawArray(cpiEncoder, payloadLength, overlay);
+ }
+ return payloadLength;
+}
+
+/**
+ * Encode the CCNx Message
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [out] packetTypePtr The type to use for the PacketType based on the message type
+ *
+ * @retval non-negative the bytes appended to the encoder
+ * @retval negative An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static ssize_t
+_encodeMessage(CCNxCodecTlvEncoder *packetEncoder, CCNxTlvDictionary *packetDictionary, CCNxCodecSchemaV1Types_PacketType *packetTypePtr)
+{
+ ssize_t startPosition = ccnxCodecTlvEncoder_Position(packetEncoder);
+ ssize_t innerLength = -1;
+
+ // what kind of message is it? need this to set the packetTypePtr
+
+ if (ccnxTlvDictionary_IsInterest(packetDictionary)) {
+ *packetTypePtr = CCNxCodecSchemaV1Types_PacketType_Interest;
+ ccnxCodecTlvEncoder_AppendContainer(packetEncoder, CCNxCodecSchemaV1Types_MessageType_Interest, 0);
+ innerLength = ccnxCodecSchemaV1MessageEncoder_Encode(packetEncoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsInterestReturn(packetDictionary)) {
+ *packetTypePtr = CCNxCodecSchemaV1Types_PacketType_InterestReturn;
+ ccnxCodecTlvEncoder_AppendContainer(packetEncoder, CCNxCodecSchemaV1Types_MessageType_Interest, 0);
+ innerLength = ccnxCodecSchemaV1MessageEncoder_Encode(packetEncoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsContentObject(packetDictionary)) {
+ *packetTypePtr = CCNxCodecSchemaV1Types_PacketType_ContentObject;
+ ccnxCodecTlvEncoder_AppendContainer(packetEncoder, CCNxCodecSchemaV1Types_MessageType_ContentObject, 0);
+ innerLength = ccnxCodecSchemaV1MessageEncoder_Encode(packetEncoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsControl(packetDictionary)) {
+ *packetTypePtr = CCNxCodecSchemaV1Types_PacketType_Control;
+ ccnxCodecTlvEncoder_AppendContainer(packetEncoder, CCNxCodecSchemaV1Types_MessageType_Control, 0);
+ innerLength = _encodeCPI(packetEncoder, packetDictionary);
+ } else if (ccnxTlvDictionary_IsManifest(packetDictionary)) {
+ *packetTypePtr = CCNxCodecSchemaV1Types_PacketType_ContentObject;
+ ccnxCodecTlvEncoder_AppendContainer(packetEncoder, CCNxCodecSchemaV1Types_MessageType_Manifest, 0);
+ innerLength = ccnxCodecSchemaV1MessageEncoder_Encode(packetEncoder, packetDictionary);
+ }
+
+ if (innerLength >= 0) {
+ // For a 0 length message, we do not backup and erase the TLV container.
+ ccnxCodecTlvEncoder_SetContainerLength(packetEncoder, startPosition, innerLength);
+ ssize_t endPosition = ccnxCodecTlvEncoder_Position(packetEncoder);
+ innerLength = endPosition - startPosition;
+ } else {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_MISSING_MANDATORY, __func__, __LINE__, ccnxCodecTlvEncoder_Position(packetEncoder));
+ ccnxCodecTlvEncoder_SetError(packetEncoder, error);
+ ccnxCodecError_Release(&error);
+ }
+
+ return innerLength;
+}
+
+static ssize_t
+_encodeValidationAlg(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t innerLength = 0;
+
+ // There must be a CryptoSuite in the packet to sign it.
+ // Temporary exception for Content Objects, which are all signed if the codec has a signer.
+ if (ccnxValidationFacadeV1_HasCryptoSuite(packetDictionary) || ccnxTlvDictionary_IsContentObject(packetDictionary)) {
+ ssize_t startPosition = ccnxCodecTlvEncoder_Position(encoder);
+
+ ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_MessageType_ValidationAlg, 0);
+ innerLength = ccnxCodecSchemaV1ValidationEncoder_EncodeAlg(encoder, packetDictionary);
+
+ if (innerLength == 0) {
+ // backup and erase the container
+ ccnxCodecTlvEncoder_SetPosition(encoder, startPosition);
+ } else if (innerLength >= 0) {
+ ccnxCodecTlvEncoder_SetContainerLength(encoder, startPosition, innerLength);
+ ssize_t endPosition = ccnxCodecTlvEncoder_Position(encoder);
+ return endPosition - startPosition;
+ }
+ }
+
+ return innerLength;
+}
+
+static ssize_t
+_encodeValidationPayload(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t startPosition = ccnxCodecTlvEncoder_Position(encoder);
+
+ ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_MessageType_ValidationPayload, 0);
+ ssize_t innerLength = ccnxCodecSchemaV1ValidationEncoder_EncodePayload(encoder, packetDictionary);
+
+ if (innerLength == 0) {
+ // backup and erase the container
+ ccnxCodecTlvEncoder_SetPosition(encoder, startPosition);
+ } else if (innerLength > 0) {
+ ccnxCodecTlvEncoder_SetContainerLength(encoder, startPosition, innerLength);
+ ssize_t endPosition = ccnxCodecTlvEncoder_Position(encoder);
+ return endPosition - startPosition;
+ }
+
+ return innerLength;
+}
+
+// =====================================================
+// Public API
+
+CCNxCodecNetworkBufferIoVec *
+ccnxCodecSchemaV1PacketEncoder_DictionaryEncode(CCNxTlvDictionary *packetDictionary, PARCSigner *signer)
+{
+ CCNxCodecNetworkBufferIoVec *outputBuffer = NULL;
+
+ CCNxCodecTlvEncoder *packetEncoder = ccnxCodecTlvEncoder_Create();
+
+ if (signer) {
+// ccnxCodecTlvEncoder_SetSigner(packetEncoder, signer);
+ }
+
+ ssize_t encodedLength = ccnxCodecSchemaV1PacketEncoder_Encode(packetEncoder, packetDictionary);
+ if (encodedLength > 0) {
+ ccnxCodecTlvEncoder_Finalize(packetEncoder);
+ outputBuffer = ccnxCodecTlvEncoder_CreateIoVec(packetEncoder);
+ }
+
+ trapUnexpectedStateIf(encodedLength < 0 && !ccnxCodecTlvEncoder_HasError(packetEncoder),
+ "Got error length but no error set");
+
+ assertFalse(ccnxCodecTlvEncoder_HasError(packetEncoder), "ENCODING ERROR")
+ {
+ printf("ERROR: %s\n", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(packetEncoder)));
+ ccnxTlvDictionary_Display(packetDictionary, 3);
+ }
+
+ ccnxCodecTlvEncoder_Destroy(&packetEncoder);
+
+ // return a reference counted copy so it won't be destroyed by ccnxCodecTlvEncoder_Destroy
+ return outputBuffer;
+}
+
+ssize_t
+ccnxCodecSchemaV1PacketEncoder_Encode(CCNxCodecTlvEncoder *packetEncoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = -1;
+
+ // We will need to go back and fixedup the headers
+ ssize_t fixedHeaderPosition = ccnxCodecTlvEncoder_Position(packetEncoder);
+ ssize_t fixedHeaderLength = _encodeFixedHeader(packetEncoder, packetDictionary, -1, 0, 0);
+
+ ssize_t optionalHeadersLength = _encodeOptionalHeaders(packetEncoder, packetDictionary);
+
+ if (optionalHeadersLength >= 0) {
+ ccnxCodecTlvEncoder_MarkSignatureStart(packetEncoder);
+
+ CCNxCodecSchemaV1Types_PacketType messageType = -1;
+
+ ssize_t messageLength = _encodeMessage(packetEncoder, packetDictionary, &messageType);
+
+ if (messageLength >= 0) {
+ // validation is optional, so it's ok if its 0 length
+ ssize_t validationAlgLength = _encodeValidationAlg(packetEncoder, packetDictionary);
+ ssize_t validationPayloadLength = 0;
+ if (validationAlgLength > 0) {
+ ccnxCodecTlvEncoder_MarkSignatureEnd(packetEncoder);
+
+ validationPayloadLength = _encodeValidationPayload(packetEncoder, packetDictionary);
+ }
+
+ if (validationAlgLength >= 0 && validationPayloadLength >= 0) {
+ // now fix up the fixed header
+ size_t endPosition = ccnxCodecTlvEncoder_Position(packetEncoder);
+
+ size_t headerLength = fixedHeaderLength + optionalHeadersLength;
+ size_t packetLength = headerLength + messageLength + validationAlgLength + validationPayloadLength;
+
+ // Will this work for InterestReturn? As long as _encodeMessage returns InterestReturn it
+ // will be ok.
+ int packetType = messageType;
+
+ ccnxCodecTlvEncoder_SetPosition(packetEncoder, fixedHeaderPosition);
+ _encodeFixedHeader(packetEncoder, packetDictionary, packetType, headerLength, packetLength);
+ ccnxCodecTlvEncoder_SetPosition(packetEncoder, endPosition);
+ length = endPosition - fixedHeaderPosition;
+
+ trapUnexpectedStateIf(packetLength != length, "packet length %zu not equal to measured length %zd", packetLength, length);
+ }
+ }
+ }
+
+ return length;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.h
new file mode 100755
index 00000000..c83f165f
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.h
@@ -0,0 +1,85 @@
+/*
+ * 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 ccnxCodecSchemaV1_PacketEncoder.h
+ * @brief Encoder for the version 1 TLV Packet
+ *
+ * Example:
+ * @code
+ * {
+ * }
+ * @endcode
+ *
+ */
+
+#ifndef CCNxCodecSchemaV1_PacketEncoder_h
+#define CCNxCodecSchemaV1_PacketEncoder_h
+
+#include <parc/algol/parc_Buffer.h>
+#include <parc/security/parc_Signer.h>
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+#include <ccnx/common/codec/ccnxCodec_EncodingBuffer.h>
+#include <ccnx/common/codec/ccnxCodec_NetworkBuffer.h>
+
+/**
+ * Encode the packetDictionary to wire format
+ *
+ * Will only use the PacketType from FixedHeader in the dictionary, if provided. The packet Version is fixed at "1",
+ * the PayloadLength and HeaderLength are calculated. If the FixedHeaderDictionary is not provided, the
+ * PacketType is inferred from the type of CCNx message.
+ *
+ * The signer is not stored beyond the call to DictionaryEncode.
+ * If the dictionary already has a ValidationAlg and ValidationPayload, those are used, not the Signer.
+ * Otherwise, if the signer is not null, it is used to sign the wire format.
+ *
+ * @param [in] packetDictionary The dictionary representation of the packet to encode
+ * @param [in] signer If not NULL will be used to sign the wire format
+ *
+ * @retval non-null An IoVec that can be written to the network
+ * @retval null an error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+CCNxCodecNetworkBufferIoVec *ccnxCodecSchemaV1PacketEncoder_DictionaryEncode(CCNxTlvDictionary *packetDictionary, PARCSigner *signer);
+
+/**
+ * Encode a packetDictionary to wire format.
+ *
+ * Will only use the PacketType from FixedHeader in the dictionary, if provided. The packet Version is fixed at "1",
+ * the PayloadLength and HeaderLength are calculated. If the FixedHeaderDictionary is not provided, the
+ * PacketType is inferred from the type of CCNx message.
+ *
+ * You must use ccnxCodecTlvEncoder_SetSigner(signer) if you require a signature or MAC on the packet.
+ *
+ * @param [in] packetEncoder A TLV packet will be appended to the encoder
+ * @param [in] packetDictionary The dictionary representation of the packet to encode
+ *
+ * @retval non-negative The total bytes appended to the encode buffer
+ * @retval -1 An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+ssize_t ccnxCodecSchemaV1PacketEncoder_Encode(CCNxCodecTlvEncoder *packetEncoder, CCNxTlvDictionary *packetDictionary);
+
+#endif // CCNxCodecSchemaV1_PacketEncoder_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.c
new file mode 100644
index 00000000..72e1ce3e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.c
@@ -0,0 +1,68 @@
+/*
+ * 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 <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Object.h>
+
+#include <LongBow/runtime.h>
+#include <ccnx/common/ccnx_PayloadType.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+CCNxTlvDictionary *
+ccnxCodecSchemaV1TlvDictionary_CreateInterest(void)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+ ccnxTlvDictionary_SetMessageType_Interest(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ return dictionary;
+}
+
+CCNxTlvDictionary *
+ccnxCodecSchemaV1TlvDictionary_CreateContentObject(void)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+ ccnxTlvDictionary_SetMessageType_ContentObject(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ return dictionary;
+}
+
+CCNxTlvDictionary *
+ccnxCodecSchemaV1TlvDictionary_CreateManifest(void)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+ ccnxTlvDictionary_SetMessageType_Manifest(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+
+ return dictionary;
+}
+
+CCNxTlvDictionary *
+ccnxCodecSchemaV1TlvDictionary_CreateControl(void)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+ ccnxTlvDictionary_SetMessageType_Control(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ return dictionary;
+}
+
+CCNxTlvDictionary *
+ccnxCodecSchemaV1TlvDictionary_CreateInterestReturn(void)
+{
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+ ccnxTlvDictionary_SetMessageType_InterestReturn(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ return dictionary;
+}
+
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h
new file mode 100755
index 00000000..e76492b6
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h
@@ -0,0 +1,250 @@
+/*
+ * 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 ccnxCodecSchemaV1_TlvDictionary.h
+ * @brief <#Brief Description#>
+ *
+ * Used as keys to the CCNxTlvDictionary for the version 1 schema
+ *
+ */
+
+#ifndef libccnx_ccnx_TlvDictionary_SchemaV1_h
+#define libccnx_ccnx_TlvDictionary_SchemaV1_h
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+
+/**
+ * @typedef CCNxCodecSchemaV1TlvDictionary_CryptoSuite
+ * @abstract The ValidationAlgorithm Type.
+ * @constant <#name#> <#description#>
+ * @discussion These are the wire-format values for the ValidationAlgorithm type. The values
+ * specified follow from the CCNx Messages RFC.
+ *
+ * It is not the same as the value stored in CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE,
+ * which is of type PARCCryptoSuite.
+ */
+typedef enum rta_tlv_schema_v1_crypto_suite {
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C = 2,
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256 = 4,
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256 = 6,
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite_EcSecp256K1 = 7,
+} CCNxCodecSchemaV1TlvDictionary_CryptoSuite;
+
+/**
+ * @typedef <#CCNBHeaderType#>
+ * @abstract <#Abstract#>
+ * @constant CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat The off-the-wire packet or a pre-encoded packet
+ * @discussion
+ * The WireFormat header is a ficticious header for holding the off-the-wire packet received
+ * from the network or to send a pre-encoded packet down through the stack.
+ *
+ * The Forwarder header is a ficticious header for holding special forwarder control block. The
+ * forwarder control block, on ingress, contains information about where a packet arrived. On
+ * egress, it contains information about how the packet should be transmitted, such as restricting
+ * it to a specific egress interface.
+ *
+ * The protected region extent is used to determine they byte range used for verification.
+ */
+
+
+typedef enum rta_tlv_schema_v1_headers_fastarray {
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_TransportStack = 0, /**< Array element 0 is used by RTA Transport stack */
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader = 1,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG = 2,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_OBJFRAG = 3,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_WireFormat = 4,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_Forwarder = 5,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime = 6,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime = 7,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedStart = 8, /**< Fictitious header for Protected Region Extent */
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedLength = 9, /**< Fictitious header for Protected Region length */
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ContentObjectHashRegionStart = 10, /**< Fictitious header for CO Hash Region Extent */
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ContentObjectHashRegionLength = 11, /**< Fictitious header for CO Hash Region length */
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestReturnCode = 12,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel = 13,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END = 14
+} CCNxCodecSchemaV1TlvDictionary_HeadersFastArray;
+
+/**
+ * The ValidationFastArray are fields that may appear in the Validation Algorithm and the Validation Payload field.
+ *
+ * Note that the ValidationFastArray_CRYPTO_SUITE is always expressed in terms of PARCCryptoSuite.
+ */
+typedef enum rta_tlv_schema_v1_validation_fastarray {
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 0,
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 1, // PARCCryptoSuite value
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 2,
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CERT = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 3,
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 4,
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_KEYID = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 5,
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_OBJHASH = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 6,
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 7,
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 8,
+ CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END = CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END + 9
+} CCNxCodecSchemaV1TlvDictionary_ValidationFastArray;
+
+
+/**
+ * The MessageFastArray are fields that may appear in the body of a CCNx message (Interest, Content Object, Control).
+ *
+ * The Hop Limit is part of the MessageFastArray even though it appears in the FixedHeader. It is treated like a property
+ * of the Interest.
+ */
+typedef enum rta_tlv_schema_v1_message_fastarray {
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 0,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 1,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 2,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 4,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 5, /***< Virtual field */
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 6,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 7,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 8,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HASH_GROUP = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 9,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_DATA_POINTER = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 10,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_MANIFEST_POINTER = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 11,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END = CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_END + 12
+} CCNxCodecSchemaV1TlvDictionary_MessageFastArray;
+
+//const int CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_PathLabel = CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END + 1;
+
+/**
+ * Each TLV container can have custom types in it, so each container has a "list"
+ * Organization Extensions go here.
+ */
+typedef enum rta_tlv_schema_v1_lists {
+ CCNxCodecSchemaV1TlvDictionary_Lists_HEADERS = 0,
+ CCNxCodecSchemaV1TlvDictionary_Lists_MESSAGE_LIST = 1,
+ CCNxCodecSchemaV1TlvDictionary_Lists_VALIDATION_ALG_LIST = 4,
+ CCNxCodecSchemaV1TlvDictionary_Lists_VALIDATION_PAYLOAD_LIST = 5,
+ CCNxCodecSchemaV1TlvDictionary_Lists_HASH_GROUP_LIST = 6,
+ CCNxCodecSchemaV1TlvDictionary_Lists_END = 7
+} CCNxCodecSchemaV1TlvDictionary_Lists;
+
+/**
+ * Creates an empty Interest dictionary
+ *
+ * The dictionary schema will be V1 and the dictionary type will be Interest. No other
+ * fields are pre-populated.
+ *
+ * @retval non-null An allocated Dictionary of type Interest
+ * @retval null An error (likely no memory)
+ *
+ * Example:
+ * @code
+ * {
+ * // in a decoder
+ * if (messageType == _DecoderTlvType_Interest) {
+ * CCNxTlvDictionary *interest = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ * // decode the rest of the packet
+ * return interest;
+ * }
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary *ccnxCodecSchemaV1TlvDictionary_CreateInterest(void);
+
+/**
+ * Creates an empty Content Object dictionary
+ *
+ * The dictionary schema will be V1 and the dictionary type will be Content Object. No other
+ * fields are pre-populated.
+ *
+ * @retval non-null An allocated Dictionary of type Content Object
+ * @retval null An error (likely no memory)
+ *
+ * Example:
+ * @code
+ * {
+ * // in a decoder
+ * if (messageType == _DecoderTlvType_ContentObject) {
+ * CCNxTlvDictionary *object = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ * // decode the rest of the packet
+ * return object;
+ * }
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary *ccnxCodecSchemaV1TlvDictionary_CreateContentObject(void);
+
+/**
+ * Creates an empty Manifest dictionary
+ *
+ * The dictionary schema will be V1 and the dictionary type will be Content Object. The
+ * PayloadType will be set to CCNxPayloadType_MANIFEST. No other fields are pre-populated.
+ *
+ * @retval non-null An allocated Dictionary of type Manifest
+ * @retval null An error (likely no memory)
+ *
+ * Example:
+ * @code
+ * {
+ * // in a decoder
+ * if (messageType == _DecoderTlvType_Manifest) {
+ * CCNxTlvDictionary *object = ccnxCodecSchemaV1TlvDictionary_Manifest();
+ * // decode the rest of the packet
+ * return object;
+ * }
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary *ccnxCodecSchemaV1TlvDictionary_CreateManifest(void);
+
+/**
+ * Creates an empty Control dictionary
+ *
+ * The dictionary schema will be V1 and the dictionary type will be Control. No other
+ * fields are pre-populated.
+ *
+ * @retval non-null An allocated Dictionary of type Control
+ * @retval null An error (likely no memory)
+ *
+ * Example:
+ * @code
+ * {
+ * // in a decoder
+ * if (messageType == _DecoderTlvType_Control) {
+ * CCNxTlvDictionary *control = ccnxCodecSchemaV1TlvDictionary_CreateControl();
+ * // decode the rest of the packet
+ * return control;
+ * }
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary *ccnxCodecSchemaV1TlvDictionary_CreateControl(void);
+
+/**
+ * Creates an empty InterestReturn dictionary
+ *
+ * The dictionary schema will be V1 and the dictionary type will be InterestReturn. No other
+ * fields are pre-populated.
+ *
+ * @retval non-null An allocated Dictionary of type InterestReturn
+ * @retval null An error (likely no memory)
+ *
+ * Example:
+ * @code
+ * {
+ * // in a decoder
+ * if (messageType == _DecoderTlvType_InterestReturn) {
+ * CCNxTlvDictionary *interestReturn = ccnxCodecSchemaV1TlvDictionary_CreateInterestReturn();
+ * // decode the rest of the packet
+ * return interestReturn;
+ * }
+ * }
+ * @endcode
+ */
+CCNxTlvDictionary *ccnxCodecSchemaV1TlvDictionary_CreateInterestReturn(void);
+#endif // libccnx_ccnx_TlvDictionary_SchemaV1_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h
new file mode 100755
index 00000000..1c50eebc
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h
@@ -0,0 +1,211 @@
+/*
+ * 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 ccnxCodecSchemaV1_Types.h
+ * @brief Common definitions for Schema version 1
+ *
+ * Defines the TLV "type" values for each field
+ *
+ */
+
+#ifndef TransportRTA_ccnxCodecSchemaV1_Types_h
+#define TransportRTA_ccnxCodecSchemaV1_Types_h
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_PacketType
+ * @abstract The values used in the PacketType field of the Fixed Header
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_packet_type {
+ CCNxCodecSchemaV1Types_PacketType_Interest = 0x00,
+ CCNxCodecSchemaV1Types_PacketType_ContentObject = 0x01,
+ CCNxCodecSchemaV1Types_PacketType_InterestReturn = 0x02,
+ CCNxCodecSchemaV1Types_PacketType_Control = 0xA4,
+} CCNxCodecSchemaV1Types_PacketType;
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_MessageType
+ * @abstract The values used in the MessageType field of the CCNx Message body
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_message_type {
+ CCNxCodecSchemaV1Types_MessageType_Interest = 0x0001,
+ CCNxCodecSchemaV1Types_MessageType_ContentObject = 0x0002,
+ CCNxCodecSchemaV1Types_MessageType_ValidationAlg = 0x0003,
+ CCNxCodecSchemaV1Types_MessageType_ValidationPayload = 0x0004,
+ CCNxCodecSchemaV1Types_MessageType_Manifest = 0x0006,
+ CCNxCodecSchemaV1Types_MessageType_Control = 0xBEEF,
+} CCNxCodecSchemaV1Types_MessageType;
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_OptionalHeadersTypes
+ * @abstract The well-known keys for the hop-by-hop headers
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_optional_headers_types {
+ CCNxCodecSchemaV1Types_OptionalHeaders_InterestLifetime = 0x0001,
+ CCNxCodecSchemaV1Types_OptionalHeaders_RecommendedCacheTime = 0x0002,
+ CCNxCodecSchemaV1Types_OptionalHeaders_PathLabel = 0x0003,
+ CCNxCodecSchemaV1Types_OptionalHeaders_InterestFragment = 0x0004,
+ CCNxCodecSchemaV1Types_OptionalHeaders_ContentObjectFragment = 0x0005,
+} CCNxCodecSchemaV1Types_OptionalHeaders;
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_PayloadType
+ * @abstract The values of the PayloadType field
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_payloadtype_types {
+ CCNxCodecSchemaV1Types_PayloadType_Data = 0,
+ CCNxCodecSchemaV1Types_PayloadType_Key = 1,
+ CCNxCodecSchemaV1Types_PayloadType_Link = 2,
+} CCNxCodecSchemaV1Types_PayloadType;
+
+// ==================================================
+// Fields in a Message Object
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_MessageTypes
+ * @abstract The well-known types inside the CCNxMessage
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_ccnxmessage_types {
+ CCNxCodecSchemaV1Types_CCNxMessage_Name = 0x0000,
+ CCNxCodecSchemaV1Types_CCNxMessage_Payload = 0x0001,
+ CCNxCodecSchemaV1Types_CCNxMessage_KeyIdRestriction = 0x0002,
+ CCNxCodecSchemaV1Types_CCNxMessage_ContentObjectHashRestriction = 0x0003,
+ CCNxCodecSchemaV1Types_CCNxMessage_PayloadType = 0x0005,
+ CCNxCodecSchemaV1Types_CCNxMessage_ExpiryTime = 0x0006,
+ CCNxCodecSchemaV1Types_CCNxMessage_HashGroup = 0x0007,
+ CCNxCodecSchemaV1Types_CCNxMessage_EndChunkNumber = 0x0019,
+} CCNxCodecSchemaV1Types_CCNxMessage;
+
+typedef enum rta_tlv_schema_v1_ccnxmanifest_hashgroup_types {
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata = 0x0001,
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroup_DataPointer = 0x0002,
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroup_ManifestPointer = 0x0003,
+} CCNxCodecSchemaV1Types_CCNxManifestHashGroup;
+
+typedef enum rta_tlv_schema_v1_ccnxmanifest_hashgroup_metadata_types {
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator = 0x0000,
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize = 0x0001,
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize = 0x0002,
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize = 0x0003,
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight = 0x0004,
+ CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256 = 0x0005,
+} CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata;
+
+// ==================================================
+// Fields in a Validation Algorithm
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_ValidationAlg
+ * @abstract The well-known keys for the ContentObject
+ * @constant <#name#> <#description#>
+ * @discussion the CCNxCodecSchemaV1Types_ValidationAlg values for the crypto suites must be the same as CCNxCodecSchemaV1Types_CryptoSuiteType
+ */
+typedef enum rta_tlv_schema_v1_validation_alg {
+ CCNxCodecSchemaV1Types_ValidationAlg_CRC32C = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C, // 0x0002
+ CCNxCodecSchemaV1Types_ValidationAlg_HMAC_SHA256 = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256, // 0x0004
+ CCNxCodecSchemaV1Types_ValidationAlg_RSA_SHA256 = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256, // 0x0006
+ CCNxCodecSchemaV1Types_ValidationAlg_EC_SECP_256K1 = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_EcSecp256K1, // 0x0007
+
+ CCNxCodecSchemaV1Types_ValidationAlg_KeyId = 0x0009,
+ CCNxCodecSchemaV1Types_ValidationAlg_PublicKey = 0x000B,
+ CCNxCodecSchemaV1Types_ValidationAlg_Cert = 0x000C,
+ CCNxCodecSchemaV1Types_ValidationAlg_KeyName = 0x000E,
+ CCNxCodecSchemaV1Types_ValidationAlg_SigTime = 0x000F,
+} CCNxCodecSchemaV1Types_ValidationAlg;
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_Link
+ * @abstract The well-known keys for the LINK body
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_link_types {
+ CCNxCodecSchemaV1Types_Link_Name = 0x0000,
+ CCNxCodecSchemaV1Types_Link_KeyIdRestriction = 0x0001,
+ CCNxCodecSchemaV1Types_Link_ContentObjectHashRestriction = 0x0002,
+} CCNxCodecSchemaV1Types_Link;
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_HashGroup
+ * @abstract The well-known keys for the Manifest HashGroup.
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_link_hash_group {
+ CCNxCodecSchemaV1Types_HashGroup_Metadata = 0x0001,
+ CCNxCodecSchemaV1Types_HashGroup_DataPointer = 0x0002,
+ CCNxCodecSchemaV1Types_HashGroup_ManifestPointer = 0x0003
+} CCNxCodecSchemaV1Types_HashGroup;
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_HashGroup
+ * @abstract The well-known keys for the Manifest HashGroup.
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_link_hash_group_metadata {
+ CCNxCodecSchemaV1Types_HashGroup_Locator = 0x0000,
+ CCNxCodecSchemaV1Types_HashGroup_ExternalMetadata = 0x0001,
+ CCNxCodecSchemaV1Types_HashGroup_BlockSize = 0x0002,
+ CCNxCodecSchemaV1Types_HashGroup_OverallDataSize = 0x0003,
+ CCNxCodecSchemaV1Types_HashGroup_OverallDataSha256 = 0x0004,
+} CCNxCodecSchemaV1Types_HashGroupMetadata;
+
+// ==================================================
+// Interest Return
+
+/**
+ * @typedef CCNxCodecSchemaV1Types_InterestReturnCode
+ * @abstract The values of the InterestReturn ReturnCode field
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_interestreturncode_types {
+ CCNxCodecSchemaV1Types_InterestReturnCode_NoRoute = 0x01,
+ CCNxCodecSchemaV1Types_InterestReturnCode_HopLimitExceeded = 0x02,
+ CCNxCodecSchemaV1Types_InterestReturnCode_NoResources = 0x03,
+ CCNxCodecSchemaV1Types_InterestReturnCode_PathError = 0x04,
+ CCNxCodecSchemaV1Types_InterestReturnCode_Prohibited = 0x05,
+ CCNxCodecSchemaV1Types_InterestReturnCode_Congestion = 0x06,
+ CCNxCodecSchemaV1Types_InterestReturnCode_MTUTooLarge = 0x07,
+} CCNxCodecSchemaV1Types_InterestReturnCode;
+
+// ==================================================
+// Hash function types
+/**
+ * @typedef CCNxCodecSchemaV1Types_HashTypes
+ * @abstract The values of the InterestReturn ReturnCode field
+ * @constant <#name#> <#description#>
+ * @discussion <#Discussion#>
+ */
+typedef enum rta_tlv_schema_v1_hash_types {
+ CCNxCodecSchemaV1Types_HashType_SHA256 = 0x01,
+ CCNxCodecSchemaV1Types_HashType_SHA512 = 0x02,
+ CCNxCodecSchemaV1Types_HashType_App
+} CCNxCodecSchemaV1Types_HashType;
+
+#endif //TransportRTA_ccnxCodecSchemaV1_Types_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.c
new file mode 100755
index 00000000..0524bcfa
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.c
@@ -0,0 +1,176 @@
+/*
+ * 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_Memory.h>
+#include <parc/algol/parc_Buffer.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.h>
+
+static bool
+_decodeKeyName(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length)
+{
+ // At this point, the decoder should point to the 1st byte of the "value" of the (type, length) continer.
+ // This is defined as a CCNxLink
+
+ bool success = false;
+
+ // this will set the decoder error if it fails.
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, length);
+ if (link != NULL) {
+ const CCNxName *name = ccnxLink_GetName(link);
+ if (name != NULL) {
+ success = ccnxTlvDictionary_PutName(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME, name);
+
+ if (success) {
+ PARCBuffer *keyid = ccnxLink_GetKeyID(link);
+ if (keyid) {
+ ccnxTlvDictionary_PutBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_KEYID, keyid);
+ }
+
+ PARCBuffer *hash = ccnxLink_GetContentObjectHash(link);
+ if (hash) {
+ ccnxTlvDictionary_PutBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_OBJHASH, hash);
+ }
+ }
+ }
+
+ if (!success) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+
+ ccnxLink_Release(&link);
+ }
+
+ return success;
+}
+
+static bool
+_decodeAlgParametersType(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length)
+{
+ bool success = false;
+ switch (type) {
+ case CCNxCodecSchemaV1Types_ValidationAlg_Cert:
+ success = ccnxCodecTlvUtilities_PutAsBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CERT);
+ break;
+
+ case CCNxCodecSchemaV1Types_ValidationAlg_KeyId:
+ success = ccnxCodecTlvUtilities_PutAsBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID);
+ break;
+
+ case CCNxCodecSchemaV1Types_ValidationAlg_KeyName:
+ // The "value" is a link
+ success = _decodeKeyName(decoder, packetDictionary, type, length);
+ break;
+
+ case CCNxCodecSchemaV1Types_ValidationAlg_SigTime:
+ // This is a time, so put it as an Integer
+ success = ccnxCodecTlvUtilities_PutAsInteger(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME);
+ break;
+
+ case CCNxCodecSchemaV1Types_ValidationAlg_PublicKey:
+ success = ccnxCodecTlvUtilities_PutAsBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY);
+ break;
+
+ default: {
+ // if we do not know the TLV type, put it in this container's unknown list
+ success = ccnxCodecTlvUtilities_PutAsListBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_Lists_VALIDATION_ALG_LIST);
+ }
+ break;
+ }
+
+ if (!success) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+ return success;
+}
+
+/**
+ * Called by _decodeAlgType() via ccnxCodecTlvUtilities_DecodeSubcontainer() to decode the
+ * algorithm specific parameters
+ */
+static bool
+_decodeAlgParameters(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary)
+{
+ return ccnxCodecTlvUtilities_DecodeContainer(decoder, packetDictionary, _decodeAlgParametersType);
+}
+
+static bool
+_decodeAlgType(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length)
+{
+ bool success = false;
+
+ PARCCryptoSuite parcSuite;
+ bool match = ccnxCodecSchemaV1CryptoSuite_TlvToParc((CCNxCodecSchemaV1TlvDictionary_CryptoSuite) type, &parcSuite);
+
+ if (match) {
+ success = ccnxTlvDictionary_PutInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE, parcSuite);
+
+ if (success) {
+ success = ccnxCodecTlvUtilities_DecodeSubcontainer(decoder, packetDictionary, type, length, _decodeAlgParameters);
+ }
+ } else {
+ // if we do not know the TLV type, put it in this container's unknown list
+ success = ccnxCodecTlvUtilities_PutAsListBuffer(decoder, packetDictionary, type, length, CCNxCodecSchemaV1TlvDictionary_Lists_VALIDATION_ALG_LIST);
+ }
+
+ if (!success) {
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder));
+ ccnxCodecTlvDecoder_SetError(decoder, error);
+ ccnxCodecError_Release(&error);
+ }
+ return success;
+}
+
+// ==================
+// Public API
+
+bool
+ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary)
+{
+ return ccnxCodecTlvUtilities_DecodeContainer(decoder, packetDictionary, _decodeAlgType);
+}
+
+
+bool
+ccnxCodecSchemaV1ValidationDecoder_DecodePayload(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary)
+{
+ bool success = false;
+ // A 0-length payload is treaded like an error
+ size_t remaining = ccnxCodecTlvDecoder_Remaining(decoder);
+ if (remaining > 0) {
+ PARCBuffer *payload = ccnxCodecTlvDecoder_GetValue(decoder, remaining);
+ success = ccnxTlvDictionary_PutBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD, payload);
+ parcBuffer_Release(&payload);
+ }
+ return success;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.h
new file mode 100755
index 00000000..c5d5a42c
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.h
@@ -0,0 +1,74 @@
+/*
+ * 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 ccnxCodecSchemaV1_ValidationDecoder.h
+ * @brief Decode the validation algorithm and payload
+ *
+ * <#Detailed Description#>
+ *
+ */
+
+#ifndef __CCNx_Common__ccnxCodecSchemaV1_ValidationDecoder__
+#define __CCNx_Common__ccnxCodecSchemaV1_ValidationDecoder__
+
+#include <stdbool.h>
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvDecoder.h>
+
+/**
+ * The decode the validation algorithm
+ *
+ * The decoder should point to byte 0 of the valdiation algorithm "value"
+ *
+ * The results are put in the provided dictionary.
+ * It is an error if the "value" does not extend to the end of
+ * the decoder.
+ *
+ * @param [in] decoder The decoder to parse
+ * @param [in] packetDictionary The results go directly in to the provided dictionary.
+ *
+ * @return true Fully parsed, no errors
+ * @return false Error decoding, decoder is left pointing to the first byte of the error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary);
+
+/**
+ * The decode the validation payload
+ *
+ * The decoder should point to byte 0 of the valdiation payload "value"
+ * The payload is an opaque block, so this function will just put the "value" in to the proper
+ * dictionary location. There's no real parsing.
+ *
+ * @param [in] decoder The decoder to parse
+ * @param [in] packetDictionary The results go directly in to the provided dictionary.
+ *
+ * @return true Fully parsed, no errors
+ * @return false Error decoding, decoder is left pointing to the first byte of the error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+bool ccnxCodecSchemaV1ValidationDecoder_DecodePayload(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary);
+
+#endif /* defined(__CCNx_Common__ccnxCodecSchemaV1_ValidationDecoder__) */
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.c
new file mode 100755
index 00000000..f7ad00aa
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.c
@@ -0,0 +1,253 @@
+/*
+ * 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 <sys/time.h>
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_Types.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_LinkCodec.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_CryptoSuite.h>
+
+static ssize_t
+_encodeKeyId(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCBuffer *keyid = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID);
+ if (keyid) {
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_ValidationAlg_KeyId, keyid);
+ }
+ return length;
+}
+
+static ssize_t
+_encodePublicKey(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCBuffer *key = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY);
+ if (key) {
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_ValidationAlg_PublicKey, key);
+ }
+ return length;
+}
+
+static ssize_t
+_encodeCertificate(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ PARCBuffer *cert = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CERT);
+ if (cert) {
+ length = ccnxCodecTlvEncoder_AppendBuffer(encoder, CCNxCodecSchemaV1Types_ValidationAlg_Cert, cert);
+ }
+ return length;
+}
+
+/**
+ * If there is a CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME entry in the dictionary, look up the
+ * optional keyid and hash restrictions, create a CCNxLink, then encode the Link.
+ */
+static ssize_t
+_encodeKeyName(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ CCNxName *keyname = ccnxTlvDictionary_GetName(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME);
+ if (keyname) {
+ PARCBuffer *keyid = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_KEYID);
+ PARCBuffer *hash = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_OBJHASH);
+ CCNxLink *link = ccnxLink_Create(keyname, keyid, hash);
+
+ size_t startPosition = ccnxCodecTlvEncoder_Position(encoder);
+ ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_ValidationAlg_KeyName, 0);
+ ssize_t innerLength = ccnxCodecSchemaV1LinkCodec_Encode(encoder, link);
+
+ if (innerLength == 0) {
+ // backup and erase the container
+ ccnxCodecTlvEncoder_SetPosition(encoder, startPosition);
+ } else if (innerLength > 0) {
+ ccnxCodecTlvEncoder_SetContainerLength(encoder, startPosition, innerLength);
+ ssize_t endPosition = ccnxCodecTlvEncoder_Position(encoder);
+ length = endPosition - startPosition;
+ } else {
+ // an error signal
+ length = innerLength;
+ }
+
+ ccnxLink_Release(&link);
+ }
+ return length;
+}
+
+/**
+ * If a time is not provided, use the current time
+ */
+static ssize_t
+_encodeSignatureTime(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+
+ bool haveSignTime = false;
+ uint64_t signTime = 0;
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME)) {
+ haveSignTime = true;
+ signTime = ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME);
+ } else {
+ // if we have a signer and with a signature algorithm, create the signing time
+ PARCSigner *signer = ccnxCodecTlvEncoder_GetSigner(encoder);
+ if (signer) {
+ PARCSigningAlgorithm alg = parcSigner_GetSigningAlgorithm(signer);
+ if (alg != PARCSigningAlgortihm_NULL && alg != PARCSigningAlgorithm_UNKNOWN) {
+ // We will generate a signature, so generate a signing time
+
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ // convert to milli-seconds
+ signTime = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ haveSignTime = true;
+ }
+ }
+ }
+
+ if (haveSignTime) {
+ length = ccnxCodecTlvEncoder_AppendUint64(encoder, CCNxCodecSchemaV1Types_ValidationAlg_SigTime, signTime);
+ }
+
+ return length;
+}
+
+static ssize_t
+_encodeAlgParameters(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ ssize_t result;
+
+ result = _encodeKeyId(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodePublicKey(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodeCertificate(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodeKeyName(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ result = _encodeSignatureTime(encoder, packetDictionary);
+ if (result < 0) {
+ return result;
+ }
+ length += result;
+
+ return length;
+}
+
+ssize_t
+ccnxCodecSchemaV1ValidationEncoder_EncodeAlg(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+ bool haveCryptoSuite = false;
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite suite;
+
+ if (ccnxTlvDictionary_IsValueInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE)) {
+ // try from dictionary
+
+ PARCCryptoSuite parcSuite = (PARCCryptoSuite) ccnxTlvDictionary_GetInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE);
+
+ haveCryptoSuite = ccnxCodecSchemaV1CryptoSuite_ParcToTlv(parcSuite, &suite);
+ } else if (ccnxTlvDictionary_IsContentObject(packetDictionary)) {
+ // deduce from the signer
+
+ PARCSigner *signer = ccnxCodecTlvEncoder_GetSigner(encoder);
+ if (signer != NULL) {
+ PARCCryptoHashType hashType = parcSigner_GetCryptoHashType(signer);
+ PARCSigningAlgorithm signAlg = parcSigner_GetSigningAlgorithm(signer);
+
+ if (ccnxCodecSchemaV1CryptoSuite_SignAndHashToTlv(signAlg, hashType, &suite)) {
+ haveCryptoSuite = true;
+ }
+ }
+ }
+
+ if (haveCryptoSuite) {
+ // write the TL container then encode any enclosed TLVs
+ ssize_t startPosition = ccnxCodecTlvEncoder_Position(encoder);
+
+ ccnxCodecTlvEncoder_AppendContainer(encoder, suite, 0);
+ ssize_t innerLength = _encodeAlgParameters(encoder, packetDictionary);
+
+ // 0 inner length is acceptable
+ if (innerLength >= 0) {
+ ccnxCodecTlvEncoder_SetContainerLength(encoder, startPosition, innerLength);
+ ssize_t endPosition = ccnxCodecTlvEncoder_Position(encoder);
+ length = endPosition - startPosition;
+ } else {
+ // an error signal
+ length = innerLength;
+ }
+ }
+ return length;
+}
+
+ssize_t
+ccnxCodecSchemaV1ValidationEncoder_EncodePayload(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary)
+{
+ ssize_t length = 0;
+
+ if (!ccnxTlvDictionary_IsValueBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD)) {
+ // try to compute a signature
+
+ // If signer is NULL, then no signature is genearted
+ PARCSigner *signer = ccnxCodecTlvEncoder_GetSigner(encoder);
+ if (signer != NULL) {
+ // user did not give us one, so fill it in
+ PARCSignature *signature = ccnxCodecTlvEncoder_ComputeSignature(encoder);
+ PARCBuffer *sigbits = parcSignature_GetSignature(signature);
+
+ // this creates its own reference to sigbits
+ ccnxTlvDictionary_PutBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD, sigbits);
+
+ // this will release our hold on sigbitsElastic and sigbits.
+ parcSignature_Release(&signature);
+ }
+ }
+
+ PARCBuffer *sigbits = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+ if (sigbits) {
+ size_t remaining = parcBuffer_Remaining(sigbits);
+ uint8_t *overlay = parcBuffer_Overlay(sigbits, 0);
+ length = ccnxCodecTlvEncoder_AppendRawArray(encoder, remaining, overlay);
+ }
+
+ return length;
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.h b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.h
new file mode 100755
index 00000000..3897a053
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationEncoder.h
@@ -0,0 +1,79 @@
+/*
+ * 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 ccnxCodecSchemaV1_ValidationEncoder.h
+ * @brief Encode the Validation Algorithm and Payload
+ *
+ * Encodes the validation algorithm and payload from the dictionary. Optionally computes
+ * a signature if one is not specified in the dictionary and the encoder has a signer.
+ *
+ */
+
+#ifndef __CCNx_Common__ccnxCodecSchemaV1_ValidationEncoder__
+#define __CCNx_Common__ccnxCodecSchemaV1_ValidationEncoder__
+
+#include <ccnx/common/internal/ccnx_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_TlvEncoder.h>
+
+/**
+ * Appends the Validation Algorithm to the packet encoder
+ *
+ * If the dictionary has a CryptoSuite specified, we will create a ValidationAlgorithm section
+ * and fill it in as per the CryptoSuite and supplied validation algorithm arguments, such as
+ * a KeyId, KeyName, Cert, etc. For most signatures, only the KeyId is mandatory, the other
+ * fields will only be specified if the user put something in the dictionary.
+ *
+ * the caller is responsible for writing the ValidationAlgorithm TL container.
+ *
+ * @param [in] encoder An allocated encoder to append to
+ * @param [in] packetDictionary The dictionary containing the optional headers
+ *
+ * @return non-negative Total bytes appended to encoder
+ * @return -1 An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+ssize_t ccnxCodecSchemaV1ValidationEncoder_EncodeAlg(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary);
+
+/**
+ * Appends the Validation Payload to the packet encoder
+ *
+ * This will append the Valdiation Payload from the dictionary, or if it is missing and the
+ * encoder has a signer, will create a signature.
+ *
+ * the caller is responsible for writing the ValidationPayload TL container.
+ *
+ * To create the signature, the caller must have used ccnxCodecTlvEncoder_MarkSignatureStart() and
+ * ccnxCodecTlvEncoder_MarkSignatureEnd() functions to specify the byte locations of the start and
+ * stop of the protected region.
+ *
+ * @param [in] encoder An allocated encoder to append to
+ * @param [in] packetDictionary The dictionary containing the optional headers
+ *
+ * @return non-negative Total bytes appended to encoder
+ * @return -1 An error
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+ssize_t ccnxCodecSchemaV1ValidationEncoder_EncodePayload(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *packetDictionary);
+
+#endif /* defined(__CCNx_Common__ccnxCodecSchemaV1_ValidationEncoder__) */
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/.gitignore b/libccnx-common/ccnx/common/codec/schema_v1/test/.gitignore
new file mode 100644
index 00000000..ffeaadf8
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/.gitignore
@@ -0,0 +1,19 @@
+*.gcno
+*.log
+*.trs
+*.o
+test_ccnxCodecSchemaV1_CryptoSuite
+test_ccnxCodecSchemaV1_FixedHeaderDecoder
+test_ccnxCodecSchemaV1_FixedHeaderEncoder
+test_ccnxCodecSchemaV1_LinkCodec
+test_ccnxCodecSchemaV1_MessageDecoder
+test_ccnxCodecSchemaV1_MessageEncoder
+test_ccnxCodecSchemaV1_NameCodec
+test_ccnxCodecSchemaV1_NameSegmentCodec
+test_ccnxCodecSchemaV1_OptionalHeadersDecoder
+test_ccnxCodecSchemaV1_OptionalHeadersEncoder
+test_ccnxCodecSchemaV1_PacketDecoder
+test_ccnxCodecSchemaV1_PacketEncoder
+test_ccnxCodecSchemaV1_TlvDictionary
+test_ccnxCodecSchemaV1_ValidationDecoder
+test_ccnxCodecSchemaV1_ValidationEncoder
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/CMakeLists.txt b/libccnx-common/ccnx/common/codec/schema_v1/test/CMakeLists.txt
new file mode 100644
index 00000000..c827a36e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/CMakeLists.txt
@@ -0,0 +1,29 @@
+# Enable gcov output for the tests
+add_definitions(--coverage)
+set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
+
+set(TestsExpectedToPass
+ test_ccnxCodecSchemaV1_CryptoSuite
+ test_ccnxCodecSchemaV1_FixedHeaderDecoder
+ test_ccnxCodecSchemaV1_FixedHeaderEncoder
+ test_ccnxCodecSchemaV1_HashCodec
+ test_ccnxCodecSchemaV1_LinkCodec
+ test_ccnxCodecSchemaV1_ManifestDecoder
+ test_ccnxCodecSchemaV1_ManifestEncoder
+ test_ccnxCodecSchemaV1_MessageDecoder
+ test_ccnxCodecSchemaV1_MessageEncoder
+ test_ccnxCodecSchemaV1_NameCodec
+ test_ccnxCodecSchemaV1_NameSegmentCodec
+ test_ccnxCodecSchemaV1_OptionalHeadersDecoder
+ test_ccnxCodecSchemaV1_OptionalHeadersEncoder
+ test_ccnxCodecSchemaV1_PacketDecoder
+ test_ccnxCodecSchemaV1_PacketEncoder
+ test_ccnxCodecSchemaV1_TlvDictionary
+ test_ccnxCodecSchemaV1_ValidationDecoder
+ test_ccnxCodecSchemaV1_ValidationEncoder
+)
+
+
+foreach(test ${TestsExpectedToPass})
+ AddTest(${test})
+endforeach()
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_CryptoSuite.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_CryptoSuite.c
new file mode 100644
index 00000000..10bc24d2
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_CryptoSuite.c
@@ -0,0 +1,154 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_CryptoSuite.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <stdio.h>
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_CryptoSuite)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_CryptoSuite)
+{
+ 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(ccnxCodecSchemaV1_CryptoSuite)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1CryptoSuite_ParcToTlv);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1CryptoSuite_TlvToParc);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1CryptoSuite_SignAndHashToTlv);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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, ccnxCodecSchemaV1CryptoSuite_ParcToTlv)
+{
+ struct test_vector {
+ PARCCryptoSuite input;
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite output;
+ bool success;
+ bool sentinel;
+ } vectors[] = {
+ { .input = PARCCryptoSuite_RSA_SHA256, .output = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256, .success = true, .sentinel = false },
+ { .input = PARCCryptoSuite_HMAC_SHA256, .output = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256, .success = true, .sentinel = false },
+ { .input = PARCCryptoSuite_NULL_CRC32C, .output = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C, .success = true, .sentinel = false },
+ { .input = PARCCryptoSuite_DSA_SHA256, .output = 0, .success = false, .sentinel = false },
+ { .input = PARCCryptoSuite_RSA_SHA512, .output = 0, .success = false, .sentinel = false },
+ { .input = PARCCryptoSuite_HMAC_SHA512, .output = 0, .success = false, .sentinel = false },
+ { .input = 13579, .output = 0, .success = false, .sentinel = false },
+ { .input = 0, .output = 0, .success = false, .sentinel = true },
+ };
+
+ for (int i = 0; !vectors[i].sentinel; i++) {
+ unsigned output;
+ bool success = ccnxCodecSchemaV1CryptoSuite_ParcToTlv(vectors[i].input, &output);
+ assertTrue(success == vectors[i].success, "Wrong return value, index %d expected %d got %d", i, vectors[i].success, success);
+ if (success) {
+ assertTrue(output == vectors[i].output, "Wrong output, index %d expected %u got %u", i, vectors[i].output, output);
+ }
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1CryptoSuite_TlvToParc)
+{
+ struct test_vector {
+ PARCCryptoSuite output;
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite input;
+ bool success;
+ bool sentinel;
+ } vectors[] = {
+ { .input = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256, .output = PARCCryptoSuite_RSA_SHA256, .success = true, .sentinel = false },
+ { .input = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256, .output = PARCCryptoSuite_HMAC_SHA256, .success = true, .sentinel = false },
+ { .input = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C, .output = PARCCryptoSuite_NULL_CRC32C, .success = true, .sentinel = false },
+ { .input = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_EcSecp256K1, .output = 0, .success = false, .sentinel = false },
+ { .input = 13579, .output = 0, .success = false, .sentinel = false },
+ { .input = 0, .output = 0, .success = false, .sentinel = true },
+ };
+
+ for (int i = 0; !vectors[i].sentinel; i++) {
+ unsigned output;
+ bool success = ccnxCodecSchemaV1CryptoSuite_TlvToParc(vectors[i].input, &output);
+ assertTrue(success == vectors[i].success, "Wrong return value, index %d expected %d got %d", i, vectors[i].success, success);
+ if (success) {
+ assertTrue(output == vectors[i].output, "Wrong output, index %d expected %u got %u", i, vectors[i].output, output);
+ }
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1CryptoSuite_SignAndHashToTlv)
+{
+ struct test_vector {
+ PARCSigningAlgorithm signAlg;
+ PARCCryptoHashType hashType;
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite output;
+ bool success;
+ bool sentinel;
+ } vectors[] = {
+ { .signAlg = PARCSigningAlgorithm_RSA, .hashType = PARCCryptoHashType_SHA256, .output = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256, .success = true, .sentinel = false },
+ { .signAlg = PARCSigningAlgorithm_HMAC, .hashType = PARCCryptoHashType_SHA256, .output = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256, .success = true, .sentinel = false },
+ { .signAlg = PARCSigningAlgortihm_NULL, .hashType = PARCCryptoHashType_CRC32C, .output = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C, .success = true, .sentinel = false },
+ { .signAlg = PARCSigningAlgorithm_RSA, .hashType = 12345, .output = 0, .success = false, .sentinel = false },
+ { .signAlg = PARCSigningAlgorithm_HMAC, .hashType = 12345, .output = 0, .success = false, .sentinel = false },
+ { .signAlg = PARCSigningAlgortihm_NULL, .hashType = 12345, .output = 0, .success = false, .sentinel = false },
+ { .signAlg = 12345, .hashType = 12345, .output = 0, .success = false, .sentinel = false },
+ { .signAlg = 0, .hashType = 0, .output = 0, .success = false, .sentinel = true },
+ };
+
+ for (int i = 0; !vectors[i].sentinel; i++) {
+ unsigned output;
+ bool success = ccnxCodecSchemaV1CryptoSuite_SignAndHashToTlv(vectors[i].signAlg, vectors[i].hashType, &output);
+ assertTrue(success == vectors[i].success, "Wrong return value, index %d expected %d got %d", i, vectors[i].success, success);
+ if (success) {
+ assertTrue(output == vectors[i].output, "Wrong output, index %d expected %u got %u", i, vectors[i].output, output);
+ }
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_CryptoSuite);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_FixedHeaderDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_FixedHeaderDecoder.c
new file mode 100644
index 00000000..7a889b58
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_FixedHeaderDecoder.c
@@ -0,0 +1,350 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_FixedHeaderDecoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+
+typedef struct test_data {
+ uint8_t *packet;
+ PARCBuffer *fixedHeader;
+ CCNxCodecTlvDecoder *decoder;
+ CCNxTlvDictionary *dictionary;
+
+ // truth table
+ uint8_t version;
+ uint8_t packetType;
+ uint16_t packetLength;
+ uint8_t hopLimit;
+ uint8_t returnCode;
+ uint8_t flags;
+ uint8_t headerLength;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->packet = parcMemory_Allocate(8);
+ assertNotNull(data->packet, "parcMemory_Allocate(%d) returned NULL", 8);
+ memcpy(data->packet, &((uint8_t[]) { 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x08 }), 8);
+
+ data->fixedHeader = parcBuffer_Wrap(data->packet, 8, 0, 8);
+ data->version = 0;
+ data->packetType = 1;
+ data->packetLength = 0x0102;
+ data->hopLimit = 3;
+ data->returnCode = 4;
+ data->flags = 5;
+ data->headerLength = 8;
+ data->decoder = ccnxCodecTlvDecoder_Create(data->fixedHeader);
+ data->dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_END);
+
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+// TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ ccnxTlvDictionary_Release(&data->dictionary);
+ ccnxCodecTlvDecoder_Destroy(&data->decoder);
+ parcBuffer_Release(&data->fixedHeader);
+ parcMemory_Deallocate((void **) &(data->packet));
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_FixedHeaderDecoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_FixedHeaderDecoder)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnxCodecSchemaV1_FixedHeaderDecoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_Decode_Underrun);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketType);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetHopLimit);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetReturnCode);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetFlags);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength_Missing);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketType_Missing);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength_Missing);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion_Missing);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_PacketLengthTooShort);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_HeaderLengthTooShort);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_PacketLengthLessHeaderLength);
+}
+
+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;
+}
+
+/**
+ * Successful decode is tested in all the _GetX functions. We only test
+ * when the buffer is too small here
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_Decode_Underrun)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ // advance the buffer so its too small
+ ccnxCodecTlvDecoder_Advance(data->decoder, 1);
+
+ size_t beforePosition = ccnxCodecTlvDecoder_Position(data->decoder);
+ bool success = ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data->decoder, data->dictionary);
+ size_t afterPosition = ccnxCodecTlvDecoder_Position(data->decoder);
+
+ assertFalse(success, "Should have failed with too small a buffer");
+ assertTrue(beforePosition == afterPosition, "Wrong postion, got %zu expected %zu", afterPosition, beforePosition);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data->decoder, data->dictionary);
+ int headerLength = ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength(data->dictionary);
+ assertTrue(headerLength == data->headerLength, "Wrong headerLength, got %d expected %d", headerLength,
+ data->headerLength);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketType)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data->decoder, data->dictionary);
+ int packetType = ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketType(data->dictionary);
+ assertTrue(packetType == data->packetType, "Wrong packetType, got %d expected %d", packetType, data->packetType);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data->decoder, data->dictionary);
+ int packetLength = ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength(data->dictionary);
+ assertTrue(packetLength == data->packetLength, "Wrong payloadLength, got %d expected %d", packetLength,
+ data->packetLength);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data->decoder, data->dictionary);
+ int version = ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion(data->dictionary);
+ assertTrue(version == data->version, "Wrong version, got %d expected %d", version, data->version);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetHopLimit)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data->decoder, data->dictionary);
+ int hopLimit = ccnxCodecSchemaV1FixedHeaderDecoder_GetHopLimit(data->dictionary);
+ assertTrue(hopLimit == data->hopLimit, "Wrong hopLimit, got %d expected %d", hopLimit, data->hopLimit);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetReturnCode)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data->decoder, data->dictionary);
+ int returnCode = ccnxCodecSchemaV1FixedHeaderDecoder_GetReturnCode(data->dictionary);
+ assertTrue(returnCode == data->returnCode, "Wrong returnCode, got %d expected %d", returnCode, data->returnCode);
+
+ // Check that the InterestReturnCode was set in the fast array, too.
+ uint8_t test =
+ ccnxTlvDictionary_GetInteger(data->dictionary,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestReturnCode);
+ assertTrue(test == data->returnCode, "Expected the dictionary to have the return code set");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetFlags)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1FixedHeaderDecoder_Decode(data->decoder, data->dictionary);
+ int flags = ccnxCodecSchemaV1FixedHeaderDecoder_GetFlags(data->dictionary);
+ assertTrue(flags == data->flags, "Wrong flags, got %d expected %d", flags, data->flags);
+}
+
+
+// ==============================
+// Tests for missing values
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // don't decode the buffer, so we're operating with an empty dictionary
+ int version = ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength(data->dictionary);
+ assertTrue(version == -1, "Wrong HeaderLength, got %d expected %d", version, -1);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketType_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // don't decode the buffer, so we're operating with an empty dictionary
+ int version = ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketType(data->dictionary);
+ assertTrue(version == -1, "Wrong PacketType, got %d expected %d", version, -1);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // don't decode the buffer, so we're operating with an empty dictionary
+ int version = ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength(data->dictionary);
+ assertTrue(version == -1, "Wrong payloadLength, got %d expected %d", version, -1);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // don't decode the buffer, so we're operating with an empty dictionary
+ int version = ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion(data->dictionary);
+ assertTrue(version == -1, "Wrong version, got %d expected %d", version, -1);
+}
+
+
+/**
+ * Packet length must be at least 8 bytes
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_PacketLengthTooShort)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxCodecSchemaV1InterestHeader header = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_Interest,
+ .packetLength = htons(3),
+ .hopLimit = 4,
+ .returnCode = 7,
+ .flags = 8,
+ .headerLength = 9,
+ };
+
+ PARCBuffer *fixedHeader = parcBuffer_Wrap(&header, 8, 0, 8);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(fixedHeader);
+
+ bool success = ccnxCodecSchemaV1FixedHeaderDecoder_Decode(decoder, data->dictionary);
+ assertFalse(success, "Did not fail on packet length too short");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&fixedHeader);
+}
+
+/**
+ * Header length must be at least 8 bytes
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_HeaderLengthTooShort)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxCodecSchemaV1InterestHeader header = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_Interest,
+ .packetLength = htons(12),
+ .hopLimit = 4,
+ .returnCode = 7,
+ .flags = 8,
+ .headerLength = 6,
+ };
+
+ PARCBuffer *fixedHeader = parcBuffer_Wrap(&header, 8, 0, 8);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(fixedHeader);
+
+ bool success = ccnxCodecSchemaV1FixedHeaderDecoder_Decode(decoder, data->dictionary);
+ assertFalse(success, "Did not fail on header length too short");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&fixedHeader);
+}
+
+/**
+ * Packet length must be no less than Header Length
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderDecoder_PacketLengthLessHeaderLength)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxCodecSchemaV1InterestHeader header = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_Interest,
+ .packetLength = htons(12),
+ .hopLimit = 4,
+ .returnCode = 7,
+ .flags = 8,
+ .headerLength = 18,
+ };
+
+ PARCBuffer *fixedHeader = parcBuffer_Wrap(&header, 8, 0, 8);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(fixedHeader);
+
+ bool success = ccnxCodecSchemaV1FixedHeaderDecoder_Decode(decoder, data->dictionary);
+ assertFalse(success, "Did not fail on packet length less than header length");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&fixedHeader);
+}
+
+// ======================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_FixedHeaderDecoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_FixedHeaderEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_FixedHeaderEncoder.c
new file mode 100755
index 00000000..4f479090
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_FixedHeaderEncoder.c
@@ -0,0 +1,174 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_FixedHeaderEncoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/codec/test/testrig_Compare.c>
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV0_FixedHeaderEncoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV0_FixedHeaderEncoder)
+{
+ 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(ccnxCodecSchemaV0_FixedHeaderEncoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderEncoder_EncodeInterest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderEncoder_EncodeContentObject);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderEncoder_EncodeInterestReturn);
+}
+
+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, ccnxCodecSchemaV1FixedHeaderEncoder_EncodeInterest)
+{
+ uint16_t packetLength = 0x0102;
+
+ CCNxCodecSchemaV1InterestHeader header = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_Interest,
+ .packetLength = packetLength,
+ .hopLimit = 4,
+ .returnCode = 7, // will be set to 0
+ .flags = 8,
+ .headerLength = 9,
+ };
+
+ CCNxCodecSchemaV1InterestHeader truth = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_Interest,
+ .packetLength = htons(packetLength),
+ .hopLimit = 4,
+ .returnCode = 0,
+ .flags = 8,
+ .headerLength = 9,
+ };
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ ssize_t length = ccnxCodecSchemaV1FixedHeaderEncoder_EncodeHeader(encoder, (CCNxCodecSchemaV1FixedHeader *) &header);
+ assertTrue(length == 8, "Wrong length, got %zd expected %d", length, 8);
+
+ testCompareEncoderToLinearMemory(encoder, length, (uint8_t *) &truth);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderEncoder_EncodeContentObject)
+{
+ uint16_t packetLength = 0x0102;
+
+ CCNxCodecSchemaV1InterestHeader header = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_ContentObject,
+ .packetLength = packetLength,
+ .hopLimit = 4, // will be set to 0
+ .returnCode = 7, // will be set to 0
+ .flags = 8, // will be set to 0
+ .headerLength = 9,
+ };
+
+ CCNxCodecSchemaV1InterestHeader truth = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_ContentObject,
+ .packetLength = htons(packetLength),
+ .hopLimit = 0,
+ .returnCode = 0,
+ .flags = 0,
+ .headerLength = 9,
+ };
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ ssize_t length = ccnxCodecSchemaV1FixedHeaderEncoder_EncodeHeader(encoder, (CCNxCodecSchemaV1FixedHeader *) &header);
+ assertTrue(length == 8, "Wrong length, got %zd expected %d", length, 8);
+
+ testCompareEncoderToLinearMemory(encoder, length, (uint8_t *) &truth);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1FixedHeaderEncoder_EncodeInterestReturn)
+{
+ uint16_t packetLength = 0x0102;
+
+ CCNxCodecSchemaV1InterestHeader header = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_InterestReturn,
+ .packetLength = packetLength,
+ .hopLimit = 4,
+ .returnCode = 7,
+ .flags = 8,
+ .headerLength = 9,
+ };
+
+ CCNxCodecSchemaV1InterestHeader truth = {
+ .version = 1,
+ .packetType = CCNxCodecSchemaV1Types_PacketType_InterestReturn,
+ .packetLength = htons(packetLength),
+ .hopLimit = 4,
+ .returnCode = 7,
+ .flags = 8,
+ .headerLength = 9,
+ };
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ ssize_t length = ccnxCodecSchemaV1FixedHeaderEncoder_EncodeHeader(encoder, (CCNxCodecSchemaV1FixedHeader *) &header);
+ assertTrue(length == 8, "Wrong length, got %zd expected %d", length, 8);
+
+ testCompareEncoderToLinearMemory(encoder, length, (uint8_t *) &truth);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV0_FixedHeaderEncoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_HashCodec.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_HashCodec.c
new file mode 100644
index 00000000..9d03ca2e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_HashCodec.c
@@ -0,0 +1,235 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_HashCodec.c"
+
+#include <stdio.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/codec/ccnxCodec_Error.h>
+
+LONGBOW_TEST_RUNNER(ccnxTlvCodec_Hash)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxTlvCodec_Hash)
+{
+ 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(ccnxTlvCodec_Hash)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue_InvalidHash);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue_InvalidLength_SHA256);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue_InvalidLength_SHA512);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue_InvalidLength_App);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1HashCodec_Encode);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1HashCodec_Encode_InvalidLength);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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, ccnxTlvCodecHash_DecodeValue)
+{
+ // -- 32-byte hash
+ uint8_t encoded[] = {
+ 0x00, CCNxCodecSchemaV1Types_HashType_SHA256, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ };
+
+ PARCBuffer *tlvBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ PARCBuffer *payloadBuffer = parcBuffer_Wrap(encoded + 4, sizeof(encoded) - 4, 0, sizeof(encoded) - 4);
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(tlvBuffer);
+ PARCCryptoHash *hash = ccnxCodecSchemaV1HashCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNotNull(hash, "got non-NULL hash when it should have been an error (null)");
+
+ assertTrue(parcCryptoHash_GetDigestType(hash) == PARCCryptoHashType_SHA256, "Expected to decode the correct hash type.");
+ assertTrue(parcBuffer_Equals(payloadBuffer, parcCryptoHash_GetDigest(hash)), "Expected the digest to match.");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNull(error, "Got null error when it should have been set");
+
+ parcCryptoHash_Release(&hash);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&tlvBuffer);
+ parcBuffer_Release(&payloadBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue_InvalidHash)
+{
+ // -- 32-byte hash
+ uint8_t encoded[] = {
+ 0x00, 0xFF, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ };
+
+ PARCBuffer *tlvBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(tlvBuffer);
+ PARCCryptoHash *hash = ccnxCodecSchemaV1HashCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(hash, "Should not have decoded an incorrect hash digest");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&tlvBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue_InvalidLength_SHA256)
+{
+ // -- 32-byte hash
+ uint8_t encoded[] = {
+ 0x00, CCNxCodecSchemaV1Types_HashType_SHA256, 0x00, 0x18,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ };
+
+ PARCBuffer *tlvBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(tlvBuffer);
+ PARCCryptoHash *hash = ccnxCodecSchemaV1HashCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(hash, "Should not have decoded a SHA256 hash digest with an incorrect length");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&tlvBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue_InvalidLength_SHA512)
+{
+ // -- 32-byte hash
+ uint8_t encoded[] = {
+ 0x00, CCNxCodecSchemaV1Types_HashType_SHA512, 0x00, 0x18,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ };
+
+ PARCBuffer *tlvBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(tlvBuffer);
+ PARCCryptoHash *hash = ccnxCodecSchemaV1HashCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(hash, "Should not have decoded a SHA512 hash digest with an incorrect length");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&tlvBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecHash_DecodeValue_InvalidLength_App)
+{
+ // -- 32-byte hash
+ uint8_t encoded[] = {
+ 0x00, CCNxCodecSchemaV1Types_HashType_App, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00,0x00,0x00, 0x00, 0x00
+ };
+
+ PARCBuffer *tlvBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(tlvBuffer);
+ PARCCryptoHash *hash = ccnxCodecSchemaV1HashCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNotNull(hash, "Should have decoded an application hash digest with an arbitrary length");
+
+ parcCryptoHash_Release(&hash);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&tlvBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1HashCodec_Encode)
+{
+ uint8_t encoded[] = {
+ 0x00, CCNxCodecSchemaV1Types_HashType_SHA256, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,
+ };
+
+ PARCBuffer *trueEncoding = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ // Create the hash
+ PARCBuffer *payloadBuffer = parcBuffer_Allocate(0x20);
+ PARCCryptoHash *expectedHash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, payloadBuffer);
+
+ // Encode it
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1HashCodec_Encode(encoder, expectedHash);
+ assertFalse(length < 0, "Got error on encode: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zd got %zd", sizeof(encoded), length);
+
+ // Check for equality
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *testEncoding = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(trueEncoding, testEncoding), "The hash was encoded incorrectly.")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueEncoding, 3);
+ printf("Got\n");
+ parcBuffer_Display(testEncoding, 3);
+ }
+
+ parcBuffer_Release(&testEncoding);
+ parcBuffer_Release(&trueEncoding);
+
+ parcCryptoHash_Release(&expectedHash);
+ parcBuffer_Release(&payloadBuffer);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1HashCodec_Encode_InvalidLength)
+{
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxTlvCodec_Hash);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_LinkCodec.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_LinkCodec.c
new file mode 100755
index 00000000..599e3a5a
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_LinkCodec.c
@@ -0,0 +1,450 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_LinkCodec.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/codec/ccnxCodec_Error.h>
+
+LONGBOW_TEST_RUNNER(ccnxTlvCodec_Name)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxTlvCodec_Name)
+{
+ 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(ccnxTlvCodec_Name)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_NameOnly);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_AllFields);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_NoName);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_ExtraField);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_DupName);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_DupKeyId);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_DupHash);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_FieldOverrun);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_Underrun);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1LinkCodec_Encode);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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, ccnxTlvCodecLink_DecodeValue_NameOnly)
+{
+ CCNxName *truth = ccnxName_CreateFromCString("lci:/3=rope");
+
+ uint8_t encoded[] = {
+ 0x00, 0x00, 0x00, 8,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNotNull(link, "got null link: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ const CCNxName *test = ccnxLink_GetName(link);
+ assertTrue(ccnxName_Equals(truth, test), "Wrong name")
+ {
+ printf("Expected\n");
+ ccnxName_Display(truth, 3);
+ printf("Got\n");
+ ccnxName_Display(test, 3);
+ }
+
+ PARCBuffer *testKeyid = ccnxLink_GetKeyID(link);
+ assertNull(testKeyid, "Got a keyid without the wire encoding for it");
+
+ PARCBuffer *testHash = ccnxLink_GetContentObjectHash(link);
+ assertNull(testHash, "got a hash without the wire encoding for it");
+
+ ccnxLink_Release(&link);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+ ccnxName_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_AllFields)
+{
+ CCNxName *truth = ccnxName_CreateFromCString("lci:/3=rope");
+
+ uint8_t encoded[] = {
+ // -- name
+ 0x00, 0x00, 0x00, 8,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e',
+ // -- keyid
+ 0x00, 0x01, 0x00, 8,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ // -- hash
+ 0x00, 0x02, 0x00, 16,
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNotNull(link, "got null link: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ const CCNxName *test = ccnxLink_GetName(link);
+ assertTrue(ccnxName_Equals(truth, test), "Wrong name")
+ {
+ printf("Expected\n");
+ ccnxName_Display(truth, 3);
+ printf("Got\n");
+ ccnxName_Display(test, 3);
+ }
+
+ PARCBuffer *keyid = parcBuffer_Wrap(encoded, sizeof(encoded), 16, 24);
+ PARCBuffer *testKeyid = ccnxLink_GetKeyID(link);
+ assertTrue(parcBuffer_Equals(keyid, testKeyid), "Wrong keyid")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(keyid, 3);
+ printf("Got\n");
+ parcBuffer_Display(testKeyid, 3);
+ }
+
+ PARCBuffer *hash = parcBuffer_Wrap(encoded, sizeof(encoded), 28, 44);
+ PARCBuffer *testHash = ccnxLink_GetContentObjectHash(link);
+ assertTrue(parcBuffer_Equals(hash, testHash), "Wrong hash")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(hash, 3);
+ printf("Got\n");
+ parcBuffer_Display(testHash, 3);
+ }
+
+ parcBuffer_Release(&hash);
+ parcBuffer_Release(&keyid);
+
+ ccnxLink_Release(&link);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+ ccnxName_Release(&truth);
+}
+
+/*
+ * wire format missing name
+ */
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_NoName)
+{
+ uint8_t encoded[] = {
+ // -- keyid
+ 0x00, 0x01, 0x00, 8,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ // -- hash
+ 0x00, 0x02, 0x00, 16,
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(link, "got non-null link when it should have been an error (null)");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Got null error when it should have been set");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+/*
+ * Wire format has an extra TLV in it that's not part of the spec
+ */
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_ExtraField)
+{
+ uint8_t encoded[] = {
+ // -- name
+ 0x00, 0x00, 0x00, 8,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e',
+ // -- keyid
+ 0x00, 0x01, 0x00, 8,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ // -- hash
+ 0x00, 0x02, 0x00, 16,
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ // -- extra
+ 0x00, 0xFF, 0x00, 4,
+ 0xc0, 0xc1, 0xc2, 0xc3,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(link, "got non-null link when it should have been an error (null)");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Got null error when it should have been set");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_DupName)
+{
+ uint8_t encoded[] = {
+ // -- name
+ 0x00, 0x00, 0x00, 8,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e',
+ // -- keyid
+ 0x00, 0x01, 0x00, 8,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ // -- hash
+ 0x00, 0x02, 0x00, 16,
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ // -- name
+ 0x00, 0x00, 0x00, 8,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e',
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(link, "got non-null link when it should have been an error (null)");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Got null error when it should have been set");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_DupKeyId)
+{
+ uint8_t encoded[] = {
+ // -- name
+ 0x00, 0x00, 0x00, 8,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e',
+ // -- keyid
+ 0x00, 0x01, 0x00, 8,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ // -- hash
+ 0x00, 0x02, 0x00, 16,
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ // -- keyid
+ 0x00, 0x01, 0x00, 8,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(link, "got non-null link when it should have been an error (null)");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Got null error when it should have been set");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_DupHash)
+{
+ uint8_t encoded[] = {
+ // -- name
+ 0x00, 0x00, 0x00, 8,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e',
+ // -- keyid
+ 0x00, 0x01, 0x00, 8,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ // -- hash
+ 0x00, 0x02, 0x00, 16,
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ // -- hash
+ 0x00, 0x02, 0x00, 16,
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(link, "got non-null link when it should have been an error (null)");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Got null error when it should have been set");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_FieldOverrun)
+{
+ // name length is beyond end of fragment
+ uint8_t encoded[] = {
+ 0x00, 0x00, 0x00, 30,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(link, "got non-null link when it should have been an error (null)");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Got null error when it should have been set");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecLink_DecodeValue_Underrun)
+{
+ // buffer is too short to even parse the T and L
+ uint8_t encoded[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ // the "2" makes it too short to parse
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, 2);
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxLink *link = ccnxCodecSchemaV1LinkCodec_DecodeValue(decoder, sizeof(encoded));
+ assertNull(link, "got non-null link when it should have been an error (null)");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Got null error when it should have been set");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+// ============
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1LinkCodec_Encode)
+{
+ uint8_t encoded[] = {
+ // -- name
+ 0x00, 0x00, 0x00, 8,
+ 0x00, 0x03, 0x00, 4,
+ 'r', 'o', 'p', 'e',
+ // -- keyid
+ 0x00, 0x01, 0x00, 8,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ // -- hash
+ 0x00, 0x02, 0x00, 16,
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ };
+
+ CCNxName *trueName = ccnxName_CreateFromCString("lci:/3=rope");
+ PARCBuffer *trueKeyId = parcBuffer_Wrap(encoded, sizeof(encoded), 16, 24);
+ PARCBuffer *trueHash = parcBuffer_Wrap(encoded, sizeof(encoded), 28, 44);
+ PARCBuffer *trueEncoding = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxLink *link = ccnxLink_Create(trueName, trueKeyId, trueHash);
+
+ // now encode it and compare the the trueEncoding
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ ssize_t length = ccnxCodecSchemaV1LinkCodec_Encode(encoder, link);
+ assertFalse(length < 0, "Got error on encode: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zd got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *testEncoding = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(trueEncoding, testEncoding), "Wrong hash")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueEncoding, 3);
+ printf("Got\n");
+ parcBuffer_Display(testEncoding, 3);
+ }
+
+ parcBuffer_Release(&testEncoding);
+ parcBuffer_Release(&trueEncoding);
+ parcBuffer_Release(&trueHash);
+ parcBuffer_Release(&trueKeyId);
+ ccnxName_Release(&trueName);
+
+ ccnxLink_Release(&link);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxTlvCodec_Name);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ManifestDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ManifestDecoder.c
new file mode 100755
index 00000000..3c1609ab
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ManifestDecoder.c
@@ -0,0 +1,267 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_ManifestDecoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include "testrig_encoder.c"
+
+#include <ccnx/common/ccnx_Manifest.h>
+
+// =========================================================================
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_ManifestDecoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_ManifestDecoder)
+{
+ 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(ccnxCodecSchemaV1_ManifestDecoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_Decode);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeType);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeHashGroup);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeHashGroupMetadata);
+}
+
+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, ccnxCodecSchemaV1ManifestDecoder_Decode)
+{
+ uint8_t rawManifest[40] = { 0x00, 0x07, 0x00, 0x24,
+ 0x00, 0x02, 0x00, 0x20,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46 };
+ PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawManifest, 40));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat);
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateManifest();
+
+ bool result = ccnxCodecSchemaV1ManifestDecoder_Decode(decoder, dict);
+ assertTrue(result, "Expected the manifest to be decoded correctly");
+
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&wireFormat);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeType)
+{
+ uint8_t rawManifest[40] = { 0x00, 0x07, 0x00, 0x24,
+ 0x00, 0x02, 0x00, 0x20,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46 };
+ PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawManifest, 40));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat);
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateManifest();
+
+ uint16_t type = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ bool result = _decodeType(decoder, dict, type, length);
+ assertTrue(result, "Expected the manifest type to be correctly decoded at the top level");
+
+ ccnxManifest_Release(&dict);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&wireFormat);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeHashGroup)
+{
+ uint8_t rawManifest[40] = { 0x00, 0x07, 0x00, 0x24,
+ 0x00, 0x02, 0x00, 0x20,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46,
+ 0x46, 0x46, 0x46, 0x46 };
+ PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawManifest, 40));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat);
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateManifest();
+
+ ccnxCodecTlvDecoder_GetType(decoder); // swallow type
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create();
+ bool result = _decodeHashGroup(decoder, dict, group, length);
+ assertTrue(result, "Expected hash group to be decoded correctly.");
+
+ PARCBuffer *expectedPointer = parcBuffer_AllocateCString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
+ CCNxManifestHashGroupPointer *pointer = ccnxManifestHashGroup_GetPointerAtIndex(group, 0);
+ const PARCBuffer *actualPointer = ccnxManifestHashGroupPointer_GetDigest(pointer);
+ assertTrue(parcBuffer_Equals(expectedPointer, actualPointer), "Expected decoded pointer to equal %s, got %s", parcBuffer_ToHexString(expectedPointer), parcBuffer_ToHexString(actualPointer));
+
+ parcBuffer_Release(&expectedPointer);
+
+ ccnxManifestHashGroup_Release(&group);
+ ccnxManifest_Release(&dict);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&wireFormat);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeHashGroupMetadata)
+{
+ // Re-build the expected metadata from the manifest
+ CCNxName *groupLocator = ccnxName_CreateFromCString("ccnx:/locator");
+ PARCBuffer *digest = parcBuffer_Allocate(16);
+ for (size_t i = 0; i < parcBuffer_Limit(digest); i++) {
+ parcBuffer_PutUint8(digest, 0);
+ }
+ parcBuffer_Flip(digest);
+ size_t entrySize = 1;
+ size_t dataSize = 2;
+ size_t blockSize = 3;
+ size_t treeHeight = 4;
+
+ // Compute the expected size of this metadata group.
+ size_t metadataSize = 4 * (4 + 8) + 4 + parcBuffer_Limit(digest) + 4 + strlen("ccnx:/locator");
+
+ // See test_ccnxCodecSchemaV1_ManifestEncoder.c for the packet construction details.
+ uint8_t rawMetadata[89] = { 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata,
+ 0x00, metadataSize,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator,
+ 0x00, strlen("ccnx:/locator"),
+ 'c', 'c',
+ 'n', 'x',
+ ':', '/',
+ 'l', 'o',
+ 'c', 'a',
+ 't', 'o',
+ 'r',
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize,
+ 0x00, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, dataSize,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize,
+ 0x00, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, blockSize,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize,
+ 0x00, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, entrySize,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight,
+ 0x00, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, treeHeight,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256,
+ 0x00, parcBuffer_Remaining(digest),
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00 };
+ PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawMetadata, sizeof(rawMetadata)));
+
+ // Create the encoder and swallow the top level container
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat);
+ ccnxCodecTlvDecoder_GetType(decoder); // swallow type
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ // Decode the metadata
+ CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create();
+ bool result = _decodeHashGroupMetadata(decoder, group, length);
+ assertTrue(result, "Expected hash group metadata to be decoded correctly.");
+
+ const CCNxName *actualLocator = ccnxManifestHashGroup_GetLocator(group);
+ size_t actualEntrySize = ccnxManifestHashGroup_GetEntrySize(group);
+ size_t actualDataSize = ccnxManifestHashGroup_GetDataSize(group);
+ size_t actualBlockSize = ccnxManifestHashGroup_GetBlockSize(group);
+ size_t actualTreeHeight = ccnxManifestHashGroup_GetTreeHeight(group);
+ const PARCBuffer *actualDigest = ccnxManifestHashGroup_GetOverallDataDigest(group);
+
+ assertTrue(ccnxName_Equals(groupLocator, actualLocator), "Expected decoded locator to equal %s, got %s", ccnxName_ToString(groupLocator), ccnxName_ToString(actualLocator));
+ assertTrue(entrySize == actualEntrySize, "Expected %zu entry size, got %zu", entrySize, actualEntrySize);
+ assertTrue(dataSize == actualDataSize, "Expected %zu data size, got %zu", dataSize, actualDataSize);
+ assertTrue(blockSize == actualBlockSize, "Expected %zu block size, got %zu", blockSize, actualBlockSize);
+ assertTrue(treeHeight == actualTreeHeight, "Expected %zu tree height, got %zu", treeHeight, actualTreeHeight);
+ assertTrue(parcBuffer_Equals(digest, actualDigest), "Expected %s digest, got %s", parcBuffer_ToHexString(digest), parcBuffer_ToHexString(actualDigest));
+
+ parcBuffer_Release(&digest);
+ ccnxName_Release(&groupLocator);
+
+ ccnxManifestHashGroup_Release(&group);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&wireFormat);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_ManifestDecoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ManifestEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ManifestEncoder.c
new file mode 100755
index 00000000..a0e36abf
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ManifestEncoder.c
@@ -0,0 +1,306 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_ManifestEncoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include "testrig_encoder.c"
+
+#include <ccnx/common/ccnx_Manifest.h>
+
+// =========================================================================
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_ManifestEncoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_ManifestEncoder)
+{
+ 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(ccnxCodecSchemaV1_ManifestEncoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1ManifestEncoder_EncodeEmpty);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1ManifestEncoder_EncodeSingleHashGroup);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1ManifestEncoder_EncodeSingleHashGroup_WithMetadata);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1ManifestEncoder_AddPointer);
+}
+
+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, ccnxCodecSchemaV1ManifestEncoder_EncodeEmpty)
+{
+ CCNxName *locator = ccnxName_CreateFromCString("lci:/name");
+ CCNxManifest *manifest = ccnxManifest_Create(locator);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ size_t result = ccnxCodecSchemaV1ManifestEncoder_Encode(encoder, manifest);
+
+ assertTrue(result == 0, "Expected an empty Manifest to be encoded to size 0, got %zu", result);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxManifest_Release(&manifest);
+ ccnxName_Release(&locator);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestEncoder_AddPointer)
+{
+ CCNxName *locator = ccnxName_CreateFromCString("ccnx:/name");
+ CCNxManifest *manifest = ccnxManifest_Create(locator);
+
+ CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create();
+ PARCBuffer *pointer = parcBuffer_Flip(parcBuffer_ParseHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+ ccnxManifestHashGroup_AppendPointer(group, CCNxManifestHashGroupPointerType_Data, pointer);
+
+ ccnxManifest_AddHashGroup(manifest, group);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ size_t result = ccnxCodecSchemaV1ManifestEncoder_Encode(encoder, manifest);
+ size_t expected = 4 + 4 + parcBuffer_Remaining(pointer); // hash group TL, pointer TL, pointer V
+
+ assertTrue(result == expected, "Expected an empty Manifest to be encoded to size %zu, got %zu", expected, result);
+
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvEncoder_CreateIoVec(encoder);
+ const struct iovec *vector = ccnxCodecNetworkBufferIoVec_GetArray(iovec);
+
+ assertTrue(vector->iov_len == expected, "Expected the IO vector to contain the encoded manifest");
+ assertTrue(memcmp(vector->iov_base + 8, parcBuffer_Overlay(pointer, parcBuffer_Remaining(pointer)), vector->iov_len - 8) == 0, "Expected the same pointer to be encoded");
+
+ uint16_t expectedType = CCNxCodecSchemaV1Types_CCNxManifestHashGroup_DataPointer;
+ uint8_t *base = (uint8_t *) vector->iov_base;
+ uint16_t actualType = (base[4] << 8) | base[5];
+ assertTrue(expectedType == actualType, "Expected the type to be written correctly as CCNxCodecSchemaV1Types_CCNxManifestHashGroup_DataPointer");
+
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+
+ // Cleanup
+ parcBuffer_Release(&pointer);
+ ccnxManifestHashGroup_Release(&group);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxManifest_Release(&manifest);
+ ccnxName_Release(&locator);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestEncoder_EncodeSingleHashGroup)
+{
+ CCNxName *locator = ccnxName_CreateFromCString("ccnx:/name");
+ CCNxManifest *manifest = ccnxManifest_Create(locator);
+
+ CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create();
+ PARCBuffer *pointer = parcBuffer_Flip(parcBuffer_ParseHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+ ccnxManifestHashGroup_AppendPointer(group, CCNxManifestHashGroupPointerType_Data, pointer);
+
+ ccnxManifest_AddHashGroup(manifest, group);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ size_t result = ccnxCodecSchemaV1ManifestEncoder_Encode(encoder, manifest);
+ size_t expected = 4 + 4 + parcBuffer_Remaining(pointer); // hash group TL, pointer TL, pointer V
+
+ assertTrue(result == expected, "Expected an empty Manifest to be encoded to size %zu, got %zu", expected, result);
+
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvEncoder_CreateIoVec(encoder);
+ const struct iovec *vector = ccnxCodecNetworkBufferIoVec_GetArray(iovec);
+
+ uint8_t expectedVector[24] = { 0x00, 0x07, 0x00, 0x14,
+ 0x00, 0x02, 0x00, 0x10,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF };
+ assertTrue(vector->iov_len == expected, "Expected the IO vector to contain the encoded manifest");
+ assertTrue(memcmp(vector->iov_base, expectedVector, vector->iov_len) == 0, "Expected the same pointer to be encoded");
+
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+
+ // Cleanup
+ parcBuffer_Release(&pointer);
+ ccnxManifestHashGroup_Release(&group);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxManifest_Release(&manifest);
+ ccnxName_Release(&locator);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestEncoder_EncodeSingleHashGroup_WithMetadata)
+{
+ CCNxName *locator = ccnxName_CreateFromCString("ccnx:/name");
+ CCNxManifest *manifest = ccnxManifest_Create(locator);
+
+ CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create();
+ PARCBuffer *pointer = parcBuffer_Flip(parcBuffer_ParseHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+ ccnxManifestHashGroup_AppendPointer(group, CCNxManifestHashGroupPointerType_Data, pointer);
+
+ // Set the metadata now
+ CCNxName *groupLocator = ccnxName_CreateFromCString("ccnx:/locator");
+ ccnxManifestHashGroup_SetLocator(group, groupLocator);
+
+ PARCBuffer *digest = parcBuffer_Allocate(16);
+ for (size_t i = 0; i < parcBuffer_Limit(digest); i++) {
+ parcBuffer_PutUint8(digest, 0);
+ }
+ parcBuffer_Flip(digest);
+ ccnxManifestHashGroup_SetOverallDataDigest(group, digest);
+
+ size_t entrySize = 1;
+ ccnxManifestHashGroup_SetEntrySize(group, entrySize);
+
+ size_t dataSize = 2;
+ ccnxManifestHashGroup_SetDataSize(group, dataSize);
+
+ size_t blockSize = 3;
+ ccnxManifestHashGroup_SetBlockSize(group, blockSize);
+
+ size_t treeHeight = 4;
+ ccnxManifestHashGroup_SetTreeHeight(group, treeHeight);
+
+ // Add the hash group to the manifest
+ ccnxManifest_AddHashGroup(manifest, group);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ size_t result = ccnxCodecSchemaV1ManifestEncoder_Encode(encoder, manifest);
+
+ // Compute the expected size with all of the metadata.
+ // This packet was crafted by hand.
+ size_t expected = 4; // hash group TL
+ expected += 4 + parcBuffer_Remaining(pointer); // pointer TL, pointer V
+ expected += 4; // metadata TL
+ expected += 4 * (4 + 8); // 64-bit integer property TLs, Vs
+ expected += 4 + parcBuffer_Remaining(digest); // digest T and V
+ expected += 4 + strlen("ccnx:/locator"); // name TL, segment TL, and segment V
+
+ // Compute only the size of the metadata
+ size_t metadataSize = expected;
+ metadataSize -= 4; // top-level TL container
+ metadataSize -= (4 + parcBuffer_Remaining(pointer)); // pointer TLV
+ metadataSize -= 4; // metadata TL container
+
+ assertTrue(result == expected, "Expected an empty Manifest to be encoded to size %zu, got %zu", expected, result);
+
+ // Now do the encoding
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvEncoder_CreateIoVec(encoder);
+ const struct iovec *vector = ccnxCodecNetworkBufferIoVec_GetArray(iovec);
+
+ uint8_t expectedVector[129] = { 0x00, 0x07,
+ 0x00, expected - 4,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata,
+ 0x00, metadataSize,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator,
+ 0x00, strlen("ccnx:/locator"),
+ 'c', 'c',
+ 'n', 'x',
+ ':', '/',
+ 'l', 'o',
+ 'c', 'a',
+ 't', 'o',
+ 'r',
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize,
+ 0x00, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, dataSize,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize,
+ 0x00, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, blockSize,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize,
+ 0x00, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, entrySize,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight,
+ 0x00, 0x08,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, treeHeight,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256,
+ 0x00, parcBuffer_Remaining(digest),
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_DataPointer,
+ 0x00, parcBuffer_Remaining(pointer),
+ 0xFF, 0xFF,
+ 0xFF, 0xFF,
+ 0xFF, 0xFF,
+ 0xFF, 0xFF,
+ 0xFF, 0xFF,
+ 0xFF, 0xFF,
+ 0xFF, 0xFF,
+ 0xFF, 0xFF };
+ assertTrue(vector->iov_len == expected, "Expected the IO vector to contain the encoded manifest");
+ assertTrue(memcmp(vector->iov_base, expectedVector, vector->iov_len) == 0, "Expected the same HashGroup to be encoded");
+
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+
+ // Cleanup
+ parcBuffer_Release(&pointer);
+ parcBuffer_Release(&digest);
+ ccnxManifestHashGroup_Release(&group);
+ ccnxName_Release(&groupLocator);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxManifest_Release(&manifest);
+ ccnxName_Release(&locator);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_ManifestEncoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_MessageDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_MessageDecoder.c
new file mode 100644
index 00000000..ab339fc1
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_MessageDecoder.c
@@ -0,0 +1,320 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_MessageDecoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h>
+
+#include "testrig_packetwrapper.c"
+
+
+// =========================================================================
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_MessageDecoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(ContentObject);
+ LONGBOW_RUN_TEST_FIXTURE(Interest);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_MessageDecoder)
+{
+ 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(ccnxCodecSchemaV1_MessageDecoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// =========================================================================
+// Utility functions to get a field in the format we expect for the testrig.
+// We cannot use the facades because those try to assert a type on the dictionary which
+// is not part of the MessageDecoder.
+
+static CCNxName *
+_getName(CCNxTlvDictionary *contentObjectDictionary)
+{
+ return ccnxTlvDictionary_GetName(contentObjectDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME);
+}
+
+static PARCBuffer *
+_getPayload(const CCNxTlvDictionary *contentObjectDictionary)
+{
+ return ccnxTlvDictionary_GetBuffer(contentObjectDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD);
+}
+
+static int64_t
+_getPayloadType(CCNxTlvDictionary *contentObjectDictionary)
+{
+ return (int64_t) ccnxTlvDictionary_GetInteger(contentObjectDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE);
+}
+
+static int64_t
+_getExpiryTime(CCNxTlvDictionary *contentObjectDictionary)
+{
+ return (int64_t) ccnxTlvDictionary_GetInteger(contentObjectDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME);
+}
+
+static int64_t
+_getEndChunkNumber(CCNxTlvDictionary *contentObjectDictionary)
+{
+ return (int64_t) ccnxTlvDictionary_GetInteger(contentObjectDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT);
+}
+
+static PARCCryptoHash *
+_getKeyIdRestriction(CCNxTlvDictionary *messageDictionary)
+{
+ return (PARCCryptoHash *) ccnxTlvDictionary_GetObject(messageDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION);
+}
+
+static PARCCryptoHash *
+_getHashRestriction(CCNxTlvDictionary *messageDictionary)
+{
+ return (PARCCryptoHash *) ccnxTlvDictionary_GetObject(messageDictionary,
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION);
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(ContentObject)
+{
+ LONGBOW_RUN_TEST_CASE(ContentObject, Name);
+ LONGBOW_RUN_TEST_CASE(ContentObject, Payload);
+ LONGBOW_RUN_TEST_CASE(ContentObject, PayloadType);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ExpiryTime);
+ LONGBOW_RUN_TEST_CASE(ContentObject, EndChunkNumber);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(ContentObject)
+{
+ longBowTestCase_SetClipBoardData(testCase,
+ commonSetup(v1_content_nameA_keyid1_rsasha256,
+ sizeof(v1_content_nameA_keyid1_rsasha256),
+ v1_content_nameA_keyid1_rsasha256_truthTableEntries,
+ V1_MANIFEST_OBJ_CONTENTOBJECT));
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(ContentObject)
+{
+ 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(ContentObject, Name)
+{
+// TestData *data = longBowTestCase_GetClipBoardData(testCase);
+// testNameGetter(data, V1_MANIFEST_OBJ_NAME, ccnxCodecSchemaV1MessageDecoder_Decode, _getName);
+}
+
+LONGBOW_TEST_CASE(ContentObject, Payload)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ testBufferGetter(data, V1_MANIFEST_OBJ_PAYLOAD, ccnxCodecSchemaV1MessageDecoder_Decode, _getPayload);
+}
+
+LONGBOW_TEST_CASE(ContentObject, PayloadType)
+{
+ // The payload type is translated from the wire format value to the CCNxPayloadType value,
+ // so this test cannot use the automated framework as the value in the dictionary will not
+ // be the same as the value in the wire format
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ bool decodeSuccess = ccnxCodecSchemaV1MessageDecoder_Decode(data->decoder, data->dictionary);
+ assertTrue(decodeSuccess, "failure on ccnxCodecSchemaV1MessageDecoder_Decode");
+
+ CCNxPayloadType testPayloadType = (CCNxPayloadType) _getPayloadType(data->dictionary);
+
+ // look up the true name buffer from the truth table
+ TlvExtent extent = getTruthTableExtent(data->truthTable, V1_MANIFEST_OBJ_PAYLOADTYPE);
+
+ PARCBuffer
+ *truthbuffer = parcBuffer_Wrap(data->packet, data->packetLength, extent.offset, extent.offset + extent.length);
+ uint64_t truthvalue = -2;
+ ccnxCodecTlvUtilities_GetVarInt(truthbuffer, parcBuffer_Remaining(truthbuffer), &truthvalue);
+
+ CCNxPayloadType truthPayloadType = -1;
+ bool success =
+ _translateWirePayloadTypeToCCNxPayloadType((CCNxCodecSchemaV1Types_PayloadType) truthvalue, &truthPayloadType);
+ assertTrue(success, "failure in _translateWirePayloadTypeToCCNxPayloadType for wireFormatValue %"
+ PRId64, truthvalue);
+
+ parcBuffer_Release(&truthbuffer);
+
+ assertTrue(truthPayloadType == testPayloadType, "Wrong value, got %d expected %d", testPayloadType,
+ truthPayloadType);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ExpiryTime)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ testInt64Getter(data, V1_MANIFEST_OBJ_EXPIRY_TIME, ccnxCodecSchemaV1MessageDecoder_Decode, _getExpiryTime);
+}
+
+LONGBOW_TEST_CASE(ContentObject, EndChunkNumber)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ testInt64Getter(data, V1_MANIFEST_OBJ_ENDSEGMENT, ccnxCodecSchemaV1MessageDecoder_Decode, _getEndChunkNumber);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Interest)
+{
+ LONGBOW_RUN_TEST_CASE(Interest, Name);
+ LONGBOW_RUN_TEST_CASE(Interest, Payload);
+ LONGBOW_RUN_TEST_CASE(Interest, KeyIdRestriction);
+ LONGBOW_RUN_TEST_CASE(Interest, HashRestriction);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Interest)
+{
+ longBowTestCase_SetClipBoardData(testCase,
+ commonSetup(v1_interest_all_fields,
+ sizeof(v1_interest_all_fields),
+ TRUTHTABLENAME(v1_interest_all_fields),
+ V1_MANIFEST_INT_INTEREST));
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Interest)
+{
+ 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(Interest, Name)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ testNameGetter(data, V1_MANIFEST_INT_NAME, ccnxCodecSchemaV1MessageDecoder_Decode, _getName);
+}
+
+LONGBOW_TEST_CASE(Interest, Payload)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ testBufferGetter(data, V1_MANIFEST_INT_PAYLOAD, ccnxCodecSchemaV1MessageDecoder_Decode, _getPayload);
+}
+
+LONGBOW_TEST_CASE(Interest, KeyIdRestriction)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ testHashGetter(data, V1_MANIFEST_INT_KEYID, ccnxCodecSchemaV1MessageDecoder_Decode, _getKeyIdRestriction);
+}
+
+LONGBOW_TEST_CASE(Interest, HashRestriction)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ testHashGetter(data, V1_MANIFEST_INT_OBJHASH, ccnxCodecSchemaV1MessageDecoder_Decode, _getHashRestriction);
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _translateWirePayloadTypeToCCNxPayloadType);
+}
+
+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, _translateWirePayloadTypeToCCNxPayloadType)
+{
+ uint32_t sentinel = 0xFFFF;
+
+ struct {
+ CCNxCodecSchemaV1Types_PayloadType wire;
+ CCNxPayloadType payloadType;
+ bool success;
+ } vectors[] = {
+ { .wire = CCNxCodecSchemaV1Types_PayloadType_Data, .payloadType = CCNxPayloadType_DATA, .success = true },
+ { .wire = CCNxCodecSchemaV1Types_PayloadType_Key, .payloadType = CCNxPayloadType_KEY, .success = true },
+ { .wire = CCNxCodecSchemaV1Types_PayloadType_Link, .payloadType = CCNxPayloadType_LINK, .success = true },
+ { .wire = -2, .payloadType = -2, .success = false },
+ { .wire = sentinel, .payloadType = sentinel }
+ };
+
+ for (int i = 0; vectors[i].wire != sentinel; i++) {
+ CCNxPayloadType payloadType = -1;
+ bool success = _translateWirePayloadTypeToCCNxPayloadType(vectors[i].wire, &payloadType);
+ assertTrue(success == vectors[i].success, "Incorrect return index %d, expected %d got %d", i,
+ vectors[i].success, success);
+
+ if (success) {
+ assertTrue(payloadType == vectors[i].payloadType, "Wrong payloadType index %d, expected %d got %d", i,
+ vectors[i].payloadType, payloadType);
+ }
+ }
+}
+
+// =========================================================================
+
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_MessageDecoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_MessageEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_MessageEncoder.c
new file mode 100644
index 00000000..49452626
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_MessageEncoder.c
@@ -0,0 +1,644 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_MessageEncoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameless_nosig.h>
+
+#include "testrig_encoder.c"
+
+#include <ccnx/common/ccnx_ContentObject.h>
+#include <ccnx/common/ccnx_Interest.h>
+
+#include <ccnx/common/internal/ccnx_InterestDefault.h>
+
+// =========================================================================
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_MessageEncoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+ LONGBOW_RUN_TEST_FIXTURE(UnknownType);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_MessageEncoder)
+{
+ 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(ccnxCodecSchemaV1_MessageEncoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(ContentObject, Interest);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObject);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObjectNameless);
+ LONGBOW_RUN_TEST_CASE(InterestReturn, InterestReturn);
+}
+
+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(ContentObject, Interest)
+{
+ // create an Interest that replicates v1_interest_all_fields
+ TlvExtent keyidExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_KEYID);
+ TlvExtent hashExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_OBJHASH);
+ TlvExtent payloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_PAYLOAD);
+ TlvExtent interestExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_INTEREST);
+
+ CCNxName *name = ccnxName_CreateFromCString("lci:/3=cool");
+ uint32_t lifetime = CCNxInterestDefault_LifetimeMilliseconds;
+ uint32_t hoplimit = CCNxInterestDefault_HopLimit;
+
+ printf("%d %d\n", keyidExtent.offset + 4, keyidExtent.offset + keyidExtent.length - 4);
+ PARCBuffer *keyid = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), keyidExtent.offset + 4, keyidExtent.offset + keyidExtent.length);
+ PARCBuffer *hash = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), hashExtent.offset + 4, hashExtent.offset + hashExtent.length);
+ PARCBuffer *payload = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), payloadExtent.offset, payloadExtent.offset + payloadExtent.length);
+
+ CCNxTlvDictionary *interest =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ name, lifetime, keyid, hash, hoplimit);
+
+ ccnxInterest_SetPayloadAndId(interest, payload);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecSchemaV1MessageEncoder_Encode(encoder, interest);
+
+ PARCBuffer *truth = parcBuffer_Wrap(v1_interest_all_fields,
+ sizeof(v1_interest_all_fields),
+ interestExtent.offset,
+ interestExtent.offset + interestExtent.length);
+
+ testCompareEncoderToBuffer(encoder, truth);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&payload);
+ parcBuffer_Release(&hash);
+ parcBuffer_Release(&keyid);
+ ccnxName_Release(&name);
+ ccnxTlvDictionary_Release(&interest);
+}
+
+LONGBOW_TEST_CASE(InterestReturn, InterestReturn)
+{
+ // create an Interest that replicates v1_interest_all_fields
+ TlvExtent keyidExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_KEYID);
+ TlvExtent hashExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_OBJHASH);
+ TlvExtent payloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_PAYLOAD);
+ TlvExtent interestExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_INTEREST);
+
+ CCNxName *name = ccnxName_CreateFromCString("lci:/3=cool");
+ uint32_t lifetime = CCNxInterestDefault_LifetimeMilliseconds;
+ uint32_t hoplimit = CCNxInterestDefault_HopLimit;
+
+ PARCBuffer *keyid = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), keyidExtent.offset + 4, keyidExtent.offset + keyidExtent.length);
+ PARCBuffer *hash = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), hashExtent.offset + 4, hashExtent.offset + hashExtent.length);
+ PARCBuffer *payload = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), payloadExtent.offset, payloadExtent.offset + payloadExtent.length);
+
+ CCNxTlvDictionary *interest =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ name, lifetime, keyid, hash, hoplimit);
+ parcBuffer_Release(&hash);
+ parcBuffer_Release(&keyid);
+ ccnxName_Release(&name);
+
+ ccnxInterest_SetPayloadAndId(interest, payload);
+ parcBuffer_Release(&payload);
+
+ CCNxInterestReturn *interestReturn =
+ ccnxInterestReturn_Create(interest, CCNxInterestReturn_ReturnCode_HopLimitExceeded);
+ ccnxTlvDictionary_Release(&interest);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecSchemaV1MessageEncoder_Encode(encoder, interestReturn);
+
+ size_t packetSize = sizeof(v1_interest_all_fields);
+ uint8_t *testPacket = (uint8_t *) parcSafeMemory_Allocate(packetSize);
+ memcpy(testPacket, v1_interest_all_fields, packetSize);
+ testPacket[1] = 0x02; //InterestReturn
+ testPacket[5] = CCNxInterestReturn_ReturnCode_HopLimitExceeded;
+
+ PARCBuffer *truth = parcBuffer_Wrap(testPacket, packetSize,
+ interestExtent.offset,
+ interestExtent.offset + interestExtent.length);
+
+ testCompareEncoderToBuffer(encoder, truth);
+
+ parcSafeMemory_Deallocate((void **) &testPacket);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+ ccnxInterestReturn_Release(&interestReturn);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ContentObjectNameless)
+{
+ // create a Content Object that replicates v1_content_nameA_keyid1_rsasha256
+ TlvExtent payloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameless_nosig), V1_MANIFEST_OBJ_PAYLOAD);
+ TlvExtent contentObjectExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameless_nosig), V1_MANIFEST_OBJ_CONTENTOBJECT);
+
+ PARCBuffer *payload = parcBuffer_Wrap(v1_content_nameless_nosig, sizeof(v1_content_nameless_nosig), payloadExtent.offset, payloadExtent.offset + payloadExtent.length);
+
+ CCNxTlvDictionary *contentobject =
+ ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ NULL, CCNxPayloadType_KEY, payload);
+
+ ccnxContentObject_SetExpiryTime(contentobject, 0x01434B198400ULL);
+ ccnxContentObject_SetFinalChunkNumber(contentobject, 0x06050403);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecSchemaV1MessageEncoder_Encode(encoder, contentobject);
+
+ PARCBuffer *truth = parcBuffer_Wrap(v1_content_nameless_nosig, sizeof(v1_content_nameless_nosig), contentObjectExtent.offset, contentObjectExtent.offset + contentObjectExtent.length);
+
+ testCompareEncoderToBuffer(encoder, truth);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&payload);
+ ccnxTlvDictionary_Release(&contentobject);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ContentObject)
+{
+ // create a Content Object that replicates v1_content_nameA_keyid1_rsasha256
+ TlvExtent payloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_PAYLOAD);
+ TlvExtent contentObjectExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_CONTENTOBJECT);
+
+ CCNxName *name = ccnxName_CreateFromCString("lci:/3=hello/0xf000=ouch");
+
+ PARCBuffer *payload = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), payloadExtent.offset, payloadExtent.offset + payloadExtent.length);
+
+ CCNxTlvDictionary *contentobject =
+ ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ name, CCNxPayloadType_KEY, payload);
+
+ ccnxContentObject_SetExpiryTime(contentobject, 0x01434B198400ULL);
+ ccnxContentObject_SetFinalChunkNumber(contentobject, 0x06050403);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecSchemaV1MessageEncoder_Encode(encoder, contentobject);
+
+ PARCBuffer *truth = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), contentObjectExtent.offset, contentObjectExtent.offset + contentObjectExtent.length);
+
+ testCompareEncoderToBuffer(encoder, truth);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&payload);
+ ccnxName_Release(&name);
+ ccnxTlvDictionary_Release(&contentobject);
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Interest)
+{
+ LONGBOW_RUN_TEST_CASE(Interest, ccnxCodecSchemaV1MessageEncoder_Encode);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Interest)
+{
+ longBowTestCase_SetClipBoardData(testCase,
+ commonSetup(v1_interest_all_fields,
+ sizeof(v1_interest_all_fields),
+ TRUTHTABLENAME(v1_interest_all_fields),
+ V1_MANIFEST_INT_INTEREST));
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Interest)
+{
+ testrigencoder_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(Interest, ccnxCodecSchemaV1MessageEncoder_Encode)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1MessageEncoder_Encode(data->encoder, data->dictionary);
+
+ testCompareEncoderToBuffer(data->encoder, data->memoryRegion);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(InterestReturn)
+{
+ LONGBOW_RUN_TEST_CASE(InterestReturn, ccnxCodecSchemaV1MessageEncoder_Encode);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(InterestReturn)
+{
+ size_t packetSize = sizeof(v1_interest_all_fields);
+ uint8_t *testPacket = (uint8_t *) parcSafeMemory_Allocate(packetSize);
+ memcpy(testPacket, v1_interest_all_fields, packetSize);
+ testPacket[1] = 0x02; //InterestReturn
+ testPacket[5] = CCNxInterestReturn_ReturnCode_HopLimitExceeded;
+
+ longBowTestCase_SetClipBoardData(testCase,
+ commonSetup(v1_interest_all_fields,
+ sizeof(v1_interest_all_fields),
+ TRUTHTABLENAME(v1_interest_all_fields),
+ V1_MANIFEST_INT_INTEREST));
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(InterestReturn)
+{
+ testrigencoder_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(InterestReturn, ccnxCodecSchemaV1MessageEncoder_Encode)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1MessageEncoder_Encode(data->encoder, data->dictionary);
+
+ testCompareEncoderToBuffer(data->encoder, data->memoryRegion);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _encodeName);
+ LONGBOW_RUN_TEST_CASE(Local, _encodePayload);
+ LONGBOW_RUN_TEST_CASE(Local, _encodePayloadType);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeExpiryTime);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeEndChunkNumber);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeKeyIdRestriction);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeContentObjectHashRestriction);
+}
+
+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;
+}
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+#include <parc/algol/parc_Varint.h>
+
+LONGBOW_TEST_CASE(Local, _encodeName)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/0xf001=foot/0xf002=toe/0xf003=nail");
+ uint8_t encoded[] = {
+ 0x00, 0x00, 0x00, 23,
+ 0xF0, 0x01, 0x00, 4,
+ 'f', 'o', 'o', 't',
+ 0xF0, 0x02, 0x00, 3,
+ 't', 'o', 'e',
+ 0xF0, 0x03, 0x00, 4,
+ 'n', 'a', 'i', 'l'
+ };
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ccnxTlvDictionary_PutName(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME, name);
+
+ _encodeName(encoder, dictionary);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ assertTrue(parcBuffer_Equals(truth, test), "buffers do not match")
+ {
+ printf("Expected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxName_Release(&name);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Local, _encodePayload)
+{
+ uint8_t payload[] = { 0xf1, 0xf2, 0xf3 };
+ uint8_t encoded[] = {
+ 0x00, 0x01, 0x00, 3,
+ 0xf1, 0xf2, 0xf3
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(payload, sizeof(payload), 0, sizeof(payload));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ccnxTlvDictionary_PutBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, buffer);
+
+ _encodePayload(encoder, dictionary);
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "buffers do not match")
+ {
+ printf("Expected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&buffer);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Local, _encodePayloadType)
+{
+ CCNxPayloadType type = CCNxPayloadType_LINK;
+
+ uint8_t encoded[] = {
+ 0x00, 0x05, 0x00, 1,
+ CCNxCodecSchemaV1Types_PayloadType_Link
+ };
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ccnxTlvDictionary_PutInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE, type);
+
+ _encodePayloadType(encoder, dictionary);
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "buffers do not match")
+ {
+ printf("Expected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeExpiryTime)
+{
+ uint64_t expiry = 0x123456789ABCDEF0ULL;
+ uint8_t encoded[] = {
+ 0x00, 0x06, 0x00, 8,
+ 0x12, 0x34, 0x56, 0x78,
+ 0x9A, 0xBC, 0xDE, 0xF0
+ };
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ccnxTlvDictionary_PutInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME, expiry);
+
+ _encodeExpiryTime(encoder, dictionary);
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "buffers do not match")
+ {
+ printf("Expected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeEndChunkNumber)
+{
+ uint64_t endChunkNumber = 0x818283ULL;
+ uint8_t encoded[] = {
+ 0x00, 0x19, 0x00, 3,
+ 0x81, 0x82, 0x83
+ };
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ccnxTlvDictionary_PutInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT, endChunkNumber);
+
+ _encodeEndChunkNumber(encoder, dictionary);
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "buffers do not match")
+ {
+ printf("Expected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeKeyIdRestriction)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x02, 0x00, 0x24,
+ 0x00, 0x01, 0x00, 0x20,
+ 0x12, 0x34, 0x56, 0x78,0x9A, 0xBC, 0xDE, 0xF0,
+ 0x12, 0x34, 0x56, 0x78,0x9A, 0xBC, 0xDE, 0xF0,
+ 0x12, 0x34, 0x56, 0x78,0x9A, 0xBC, 0xDE, 0xF0,
+ 0x12, 0x34, 0x56, 0x78,0x9A, 0xBC, 0xDE, 0xF0,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 8, sizeof(encoded));
+ PARCCryptoHash *hash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, buffer);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ccnxTlvDictionary_PutObject(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION, hash);
+
+ _encodeKeyIdRestriction(encoder, dictionary);
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "buffers do not match")
+ {
+ printf("Expected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&buffer);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&dictionary);
+ parcCryptoHash_Release(&hash);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeContentObjectHashRestriction)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x03, 0x00, 0x24,
+ 0x00, 0x01, 0x00, 0x20,
+ 0x12, 0x34, 0x56, 0x78,0x9A, 0xBC, 0xDE, 0xF0,
+ 0x12, 0x34, 0x56, 0x78,0x9A, 0xBC, 0xDE, 0xF0,
+ 0x12, 0x34, 0x56, 0x78,0x9A, 0xBC, 0xDE, 0xF0,
+ 0x12, 0x34, 0x56, 0x78,0x9A, 0xBC, 0xDE, 0xF0,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 8, sizeof(encoded));
+ PARCCryptoHash *hash = parcCryptoHash_Create(PARCCryptoHashType_SHA256, buffer);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ccnxTlvDictionary_PutObject(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION, hash);
+
+ _encodeContentObjectHashRestriction(encoder, dictionary);
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "buffers do not match")
+ {
+ printf("Expected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&buffer);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&dictionary);
+ parcCryptoHash_Release(&hash);
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(UnknownType)
+{
+ LONGBOW_RUN_TEST_CASE(UnknownType, Unknown);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(UnknownType)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(UnknownType)
+{
+ 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(UnknownType, Unknown)
+{
+ CCNxTlvDictionary *unknown = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, 1);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1MessageEncoder_Encode(encoder, unknown);
+ assertTrue(length < 0, "Did not get error return when encoding unknown type");
+
+ CCNxCodecError *error = ccnxCodecTlvEncoder_GetError(encoder);
+ assertNotNull(error, "encoder did not set the error");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&unknown);
+}
+
+// ==================================================================================
+
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_MessageEncoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_NameCodec.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_NameCodec.c
new file mode 100755
index 00000000..8a33a0e2
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_NameCodec.c
@@ -0,0 +1,139 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_NameCodec.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(ccnxTlvCodec_Name)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxTlvCodec_Name)
+{
+ 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(ccnxTlvCodec_Name)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecName_Decode_RightType);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecName_Decode_WrongType);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecName_Encode);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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, ccnxTlvCodecName_Decode_RightType)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("brandywine");
+ CCNxNameSegment *segment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, buffer);
+ CCNxName *truth = ccnxName_Append(ccnxName_Create(), segment);
+ ccnxNameSegment_Release(&segment);
+ parcBuffer_Release(&buffer);
+
+ uint8_t decodeBytes[] = { 0x10, 0x20, 0x00, 0x0E, 0x00, CCNxNameLabelType_NAME, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
+ PARCBuffer *decodeBuffer = parcBuffer_Wrap(decodeBytes, sizeof(decodeBytes), 0, sizeof(decodeBytes));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(decodeBuffer);
+ CCNxName *test = ccnxCodecSchemaV1NameCodec_Decode(decoder, 0x1020);
+
+ assertTrue(ccnxName_Equals(truth, test), "Name segments do not match");
+
+ ccnxName_Release(&test);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&decodeBuffer);
+ ccnxName_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecName_Decode_WrongType)
+{
+ uint8_t decodeBytes[] = { 0x10, 0x20, 0x00, 0x0E, 0x00, CCNxNameLabelType_NAME, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
+ PARCBuffer *decodeBuffer = parcBuffer_Wrap(decodeBytes, sizeof(decodeBytes), 0, sizeof(decodeBytes));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(decodeBuffer);
+ CCNxName *test = ccnxCodecSchemaV1NameCodec_Decode(decoder, 0xFFFF);
+
+ assertNull(test, "Name should have returned NULL because the name type does not match");
+ assertTrue(ccnxCodecTlvDecoder_Position(decoder) == 0, "Position should not have moved, expected 0, got %zu", ccnxCodecTlvDecoder_Position(decoder));
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&decodeBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecName_Encode)
+{
+ uint8_t truthBytes[] = { 0x10, 0x20, 0x00, 0x0E, 0x00, CCNxNameLabelType_NAME, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
+ PARCBuffer *truth = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+
+ PARCBuffer *buffer = parcBuffer_WrapCString("brandywine");
+ CCNxNameSegment *segment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, buffer);
+
+ CCNxName *name = ccnxName_Append(ccnxName_Create(), segment);
+ ccnxNameSegment_Release(&segment);
+ parcBuffer_Release(&buffer);
+
+ ccnxCodecSchemaV1NameCodec_Encode(encoder, 0x1020, name);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ if (!parcBuffer_Equals(truth, test)) {
+ printf("Buffers do not match\n");
+ printf("Excpected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers do not match");
+ }
+
+ ccnxName_Release(&name);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxTlvCodec_Name);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_NameSegmentCodec.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_NameSegmentCodec.c
new file mode 100755
index 00000000..77800055
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_NameSegmentCodec.c
@@ -0,0 +1,149 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_NameSegmentCodec.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h>
+
+LONGBOW_TEST_RUNNER(ccnxTlvCodec_Name)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxTlvCodec_Name)
+{
+ 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(ccnxTlvCodec_Name)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecNameSegment_Decode);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecNameSegment_Decode_TLShort);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecNameSegment_Decode_VShort);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecNameSegment_Decode);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxTlvCodecNameSegment_Encode);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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, ccnxTlvCodecNameSegment_Decode)
+{
+ PARCBuffer *buffer = parcBuffer_WrapCString("brandywine");
+ CCNxNameSegment *truth = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, buffer);
+ parcBuffer_Release(&buffer);
+
+ uint8_t decodeBytes[] = { 0x00, CCNxNameLabelType_NAME, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
+ PARCBuffer *decodeBuffer = parcBuffer_Wrap(decodeBytes, sizeof(decodeBytes), 0, sizeof(decodeBytes));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(decodeBuffer);
+ CCNxNameSegment *test = ccnxCodecSchemaV1NameSegmentCodec_Decode(decoder);
+
+ assertTrue(ccnxNameSegment_Equals(truth, test), "Name segments do not match");
+
+ ccnxNameSegment_Release(&test);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&decodeBuffer);
+ ccnxNameSegment_Release(&truth);
+}
+
+/**
+ * In this case, there are not enough bytes in the buffer to decode the T and L
+ */
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecNameSegment_Decode_TLShort)
+{
+ uint8_t decodeBytes[] = { 0x00, CCNxNameLabelType_NAME, 0x00, 0x0A, 'b', 'r', 'a' };
+ PARCBuffer *decodeBuffer = parcBuffer_Wrap(decodeBytes, sizeof(decodeBytes), 0, sizeof(decodeBytes));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(decodeBuffer);
+ CCNxNameSegment *test = ccnxCodecSchemaV1NameSegmentCodec_Decode(decoder);
+
+ assertNull(test, "Name segments should have been null because there are not enough bytes in buffer");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&decodeBuffer);
+}
+
+/**
+ * In this case, we decode the T and L, but there are not enough bytes for the V
+ */
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecNameSegment_Decode_VShort)
+{
+ uint8_t decodeBytes[] = { 0x00, CCNxNameLabelType_NAME, 0x00 };
+ PARCBuffer *decodeBuffer = parcBuffer_Wrap(decodeBytes, sizeof(decodeBytes), 0, sizeof(decodeBytes));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(decodeBuffer);
+ CCNxNameSegment *test = ccnxCodecSchemaV1NameSegmentCodec_Decode(decoder);
+
+ assertNull(test, "Name segments should have been null because there are not enough bytes in buffer");
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&decodeBuffer);
+}
+
+
+LONGBOW_TEST_CASE(Global, ccnxTlvCodecNameSegment_Encode)
+{
+ uint8_t truthBytes[] = { 0x00, CCNxNameLabelType_NAME, 0x00, 0x0A, 'b', 'r', 'a', 'n', 'd', 'y', 'w', 'i', 'n', 'e' };
+ PARCBuffer *truth = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+
+ PARCBuffer *buffer = parcBuffer_WrapCString("brandywine");
+ CCNxNameSegment *segment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, buffer);
+ parcBuffer_Release(&buffer);
+
+ ccnxCodecSchemaV1NameSegmentCodec_Encode(encoder, segment);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers do not match");
+
+ parcBuffer_Release(&test);
+ ccnxNameSegment_Release(&segment);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+}
+
+int
+main(int argc, char *argv[argc])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxTlvCodec_Name);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_OptionalHeadersDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_OptionalHeadersDecoder.c
new file mode 100644
index 00000000..abe47608
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_OptionalHeadersDecoder.c
@@ -0,0 +1,321 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_OptionalHeadersDecoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <inttypes.h>
+
+#include <LongBow/unit-test.h>
+
+typedef struct test_data {
+ PARCBuffer *optionalHeader;
+ CCNxCodecTlvDecoder *decoder;
+ CCNxTlvDictionary *dictionary;
+
+ // truth table
+ PARCBuffer *interestLifetime;
+ PARCBuffer *cacheTime;
+ PARCBuffer *interestFrag;
+ PARCBuffer *objectFrag;
+ PARCBuffer *customHeader;
+
+ // the key for the customHeader
+ uint16_t customHeaderType;
+} TestData;
+
+/**
+ * A packet with all the defined optional headers plus one custom header
+ * This is not actually a packet one would see in real life as it has
+ * headers from both an Interest and a Content Object
+ */
+static uint8_t packet_with_headers[] = {
+ 0x01, 0x01, 0x00, 120, // ver = 1, type = interest, length = 120
+ 0x01, 0x00, 0x00, 88, // hopLimit = 1, reserved = 0, header length = 88
+ // ------------------------
+ // byte 8
+ 0x00, 0x01, 0x00, 0x08, // Interest Lifetime (type 1)
+ 0x20, 0x30, 0x40, 0x50, // 0x2030405060708090
+ 0x60, 0x70, 0x80, 0x90,
+ // ------------------------
+ // byte 20
+ 0x00, 0x02, 0x00, 0x08, // Recommended Cache Time (type 2)
+ 0x21, 0x31, 0x41, 0x51, // 0x2030405060708090
+ 0x61, 0x71, 0x81, 0x91,
+ // ------------------------
+ // byte 32
+ 0x00, 0x03, 0x00, 0x0C, // Interest Fragment (type 3)
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, // fragment 0x0102030405060708
+ 0x05, 0xDC, 0x04, 0x00, // MTU 1500, fragcnt 4, fragnum 0
+ // ------------------------
+ // byte 48
+ 0x00, 0x04, 0x00, 20, // ContentObject Fragment (type 4)
+ 0xC1, 0xC2, 0xC3, 0xC4,
+ 0xC5, 0xC6, 0xC7, 0xC8, // fragment 0xC1C2C3C4C5C6C7C8
+ 0x05, 0xDC, 0x04, 0x00, // MTU 1500, fragcnt 4, fragnum 0
+ 0xD1, 0xD2, 0xD3, 0xD4,
+ 0xD5, 0xD6, 0xD7, 0xD8, // fragment 0xD1D2D3D4D5D6D7D8
+ // ------------------------
+ // byte 72
+ 0x01, 0x00, 0x00, 12, // Custom header (type 256), length 12
+ 0xA0, 0xA1, 0xA2, 0xA3,
+ 0xA4, 0xA5, 0xA6, 0xA7,
+ 0xA8, 0xA9, 0xAA, 0xAB,
+ // ------------------------
+ // byte 88
+ 0x00, 0x01, 0x00, 29, // type = interest, length = 29
+ // ------------------------
+ 0x00, 0x00, 0x00, 0x10, // type = name, length = 16
+ 0x00, 0x02, 0x00, 0x04, // type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 0xF0, 0x00, 0x00, 0x04, // type = app, length = 4
+ 'o', 'u', 'c', 'h', // "ouch"
+ // ------------------------
+ 0x00, 0x01, 0x00, 0x04, // type = keyid, length = 4
+ 0xA0, 0xB0, 0xC0, 0xD0, // 0xA0B0C0D0
+ // ------------------------
+ // byte 120
+};
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ // setup the decoder and decode the optional headers
+ data->optionalHeader = parcBuffer_Wrap(packet_with_headers, sizeof(packet_with_headers), 8, 88);
+ data->decoder = ccnxCodecTlvDecoder_Create(data->optionalHeader);
+ data->dictionary = ccnxTlvDictionary_Create(10, 5);
+
+ // setup the truth values
+ data->interestLifetime = parcBuffer_Wrap(packet_with_headers, sizeof(packet_with_headers), 12, 20);
+ data->cacheTime = parcBuffer_Wrap(packet_with_headers, sizeof(packet_with_headers), 24, 32);
+
+ data->interestFrag = parcBuffer_Wrap(packet_with_headers, sizeof(packet_with_headers), 36, 48);
+ data->objectFrag = parcBuffer_Wrap(packet_with_headers, sizeof(packet_with_headers), 52, 72);
+
+ data->customHeader = parcBuffer_Wrap(packet_with_headers, sizeof(packet_with_headers), 76, 88);
+ data->customHeaderType = 0x0100;
+
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxTlvDictionary_Release(&data->dictionary);
+ ccnxCodecTlvDecoder_Destroy(&data->decoder);
+ parcBuffer_Release(&data->optionalHeader);
+
+ parcBuffer_Release(&data->interestLifetime);
+ parcBuffer_Release(&data->cacheTime);
+ parcBuffer_Release(&data->interestFrag);
+ parcBuffer_Release(&data->objectFrag);
+ parcBuffer_Release(&data->customHeader);
+
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_OptionalHeadersDecoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_OptionalHeadersDecoder)
+{
+ 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(ccnxCodecSchemaV1_OptionalHeadersDecoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_Decode_TooLong);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetContentObjectFragmentHeader);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestFragmentHeader);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestLifetimeHeader);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetRecommendedCacheTimeHeader);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetCustomHeader);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetContentObjectFragmentHeader_Missing);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestFragmentHeader_Missing);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestLifetimeHeader_Missing);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetRecommendedCacheTimeHeader_Missing);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetCustomHeader_Missing);
+}
+
+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;
+}
+
+/**
+ * One of the TLVs will extend beyond the end of the buffer. Should fail.
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_Decode_TooLong)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // Make one of the fields 255 bytes
+ uint8_t original = packet_with_headers[10];
+ packet_with_headers[10] = 0xFF;
+ bool success = ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(data->decoder, data->dictionary);
+
+ // now set it back
+ packet_with_headers[10] = original;
+
+ assertFalse(success, "Should have failed to parse when a TLV exceeds bounary");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetContentObjectFragmentHeader)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(data->decoder, data->dictionary);
+ PARCBuffer *test = ccnxCodecSchemaV1OptionalHeadersDecoder_GetContentObjectFragmentHeader(data->dictionary);
+ assertTrue(parcBuffer_Equals(test, data->objectFrag), "Wrong value")
+ {
+ printf("Expected: \n");
+ parcBuffer_Display(data->objectFrag, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestFragmentHeader)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(data->decoder, data->dictionary);
+ PARCBuffer *test = ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestFragmentHeader(data->dictionary);
+ assertTrue(parcBuffer_Equals(test, data->interestFrag), "Wrong value")
+ {
+ printf("Expected: \n");
+ parcBuffer_Display(data->interestFrag, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestLifetimeHeader)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(data->decoder, data->dictionary);
+ uint64_t lifetime = ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestLifetimeHeader(data->dictionary);
+
+ uint64_t trueLifetime = 0;
+ ccnxCodecTlvUtilities_GetVarInt(data->interestLifetime, parcBuffer_Remaining(data->interestLifetime), &trueLifetime);
+
+ assertTrue(trueLifetime == lifetime, "wrong value, expected %" PRIx64 " got %" PRIx64, trueLifetime, lifetime);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetRecommendedCacheTimeHeader)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(data->decoder, data->dictionary);
+ uint64_t cachetime = ccnxCodecSchemaV1OptionalHeadersDecoder_GetRecommendedCacheTimeHeader(data->dictionary);
+
+ uint64_t trueCachetime = 0;
+ ccnxCodecTlvUtilities_GetVarInt(data->cacheTime, parcBuffer_Remaining(data->cacheTime), &trueCachetime);
+
+ assertTrue(trueCachetime == cachetime, "wrong value, expected %" PRIx64 " got %" PRIx64, trueCachetime, cachetime);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetCustomHeader)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecSchemaV1OptionalHeadersDecoder_Decode(data->decoder, data->dictionary);
+ PARCBuffer *test = ccnxCodecSchemaV1OptionalHeadersDecoder_GetCustomType(data->dictionary, data->customHeaderType);
+ assertTrue(parcBuffer_Equals(test, data->customHeader), "Wrong value for header type %02X", data->customHeaderType)
+ {
+ printf("Expected: \n");
+ parcBuffer_Display(data->customHeader, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+}
+
+// ========
+// test for missing values
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetContentObjectFragmentHeader_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = ccnxCodecSchemaV1OptionalHeadersDecoder_GetContentObjectFragmentHeader(data->dictionary);
+ assertNull(test, "Did not get null buffer for missing field, got %p", (void *) test);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestFragmentHeader_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestFragmentHeader(data->dictionary);
+ assertNull(test, "Did not get null buffer for missing field, got %p", (void *) test);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetInterestLifetimeHeader_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ bool exists = ccnxTlvDictionary_IsValueInteger(data->dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime);
+ assertFalse(exists, "Dictionary reports it has a missing field");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetRecommendedCacheTimeHeader_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ bool exists = ccnxTlvDictionary_IsValueInteger(data->dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime);
+ assertFalse(exists, "Dictionary reports it has a missing field");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1OptionalHeadersDecoder_GetCustomHeader_Missing)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = ccnxCodecSchemaV1OptionalHeadersDecoder_GetCustomType(data->dictionary, data->customHeaderType);
+ assertNull(test, "Did not get null buffer for missing field, got %p", (void *) test);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_OptionalHeadersDecoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_OptionalHeadersEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_OptionalHeadersEncoder.c
new file mode 100644
index 00000000..1950eef2
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_OptionalHeadersEncoder.c
@@ -0,0 +1,205 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_OptionalHeadersEncoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.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 "testrig_encoder.c"
+
+static TruthTableEntry
+TRUTHTABLENAME(interest_optional_headers)[] =
+{
+ { .wellKnownType = false, .indexOrKey = V1_MANIFEST_INT_OPTHEAD, .bodyManifest = true, .extent = { 8, 28 } }, // index = 0
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_E2EFRAG, .bodyManifest = false, .extent = { 12, 12 } }, // index = 1
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_LIFETIME, .bodyManifest = false, .extent = { 28, 8 } }, // index = 2
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+static TruthTableEntry
+TRUTHTABLENAME(contentobject_optional_headers)[] =
+{
+ { .wellKnownType = false, .indexOrKey = V1_MANIFEST_OBJ_OPTHEAD, .bodyManifest = true, .extent = { 8, 36 } }, // 0
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_E2EFRAG, .bodyManifest = false, .extent = { 12, 20 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_RecommendedCacheTime, .bodyManifest = false, .extent = { 36, 8 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV0_OptionalHeadersEncoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Interest);
+ LONGBOW_RUN_TEST_FIXTURE(ContentObject);
+ LONGBOW_RUN_TEST_FIXTURE(UnknownType);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV0_OptionalHeadersEncoder)
+{
+ 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(ccnxCodecSchemaV0_OptionalHeadersEncoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ==================================================================================
+
+LONGBOW_TEST_FIXTURE(Interest)
+{
+ LONGBOW_RUN_TEST_CASE(Interest, ccnxCodecSchemaV1OptionalHeadersEncoder_Encode);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Interest)
+{
+ longBowTestCase_SetClipBoardData(testCase,
+ commonSetup(v1_interest_nameA,
+ sizeof(v1_interest_nameA),
+ TRUTHTABLENAME(interest_optional_headers),
+ V1_MANIFEST_INT_OPTHEAD));
+
+ // commonSetup will not add headers...
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ addBuffer(data, data->dictionary, TRUTHTABLENAME(interest_optional_headers)[1].extent.offset, TRUTHTABLENAME(interest_optional_headers)[1].extent.offset + TRUTHTABLENAME(interest_optional_headers)[1].extent.length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG);
+
+ addBuffer(data, data->dictionary, TRUTHTABLENAME(interest_optional_headers)[2].extent.offset, TRUTHTABLENAME(interest_optional_headers)[2].extent.offset + TRUTHTABLENAME(interest_optional_headers)[2].extent.length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime);
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Interest)
+{
+ testrigencoder_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(Interest, ccnxCodecSchemaV1OptionalHeadersEncoder_Encode)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ssize_t length = ccnxCodecSchemaV1OptionalHeadersEncoder_Encode(data->encoder, data->dictionary);
+ assertTrue(length >= 0, "Error on Encode: length %zd", length);
+ testCompareEncoderToBuffer(data->encoder, data->memoryRegion);
+}
+
+// ==================================================================================
+
+LONGBOW_TEST_FIXTURE(ContentObject)
+{
+ LONGBOW_RUN_TEST_CASE(ContentObject, ccnxCodecSchemaV1OptionalHeadersEncoder_Encode);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(ContentObject)
+{
+ longBowTestCase_SetClipBoardData(testCase,
+ commonSetup(v1_content_nameA_crc32c,
+ sizeof(v1_content_nameA_crc32c),
+ TRUTHTABLENAME(contentobject_optional_headers),
+ V1_MANIFEST_OBJ_OPTHEAD));
+
+ // commonSetup will not add headers...
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ addBuffer(data, data->dictionary, TRUTHTABLENAME(contentobject_optional_headers)[1].extent.offset, TRUTHTABLENAME(contentobject_optional_headers)[1].extent.offset + TRUTHTABLENAME(contentobject_optional_headers)[1].extent.length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_OBJFRAG);
+
+ addBuffer(data, data->dictionary, TRUTHTABLENAME(contentobject_optional_headers)[2].extent.offset, TRUTHTABLENAME(contentobject_optional_headers)[2].extent.offset + TRUTHTABLENAME(contentobject_optional_headers)[2].extent.length, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_RecommendedCacheTime);
+
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(ContentObject)
+{
+ testrigencoder_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(ContentObject, ccnxCodecSchemaV1OptionalHeadersEncoder_Encode)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ssize_t length = ccnxCodecSchemaV1OptionalHeadersEncoder_Encode(data->encoder, data->dictionary);
+ assertTrue(length >= 0, "Error on Encode: length %zd", length);
+ testCompareEncoderToBuffer(data->encoder, data->memoryRegion);
+}
+
+// ==================================================================================
+
+LONGBOW_TEST_FIXTURE(UnknownType)
+{
+ LONGBOW_RUN_TEST_CASE(UnknownType, Unknown);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(UnknownType)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(UnknownType)
+{
+ 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(UnknownType, Unknown)
+{
+ CCNxTlvDictionary *unknown = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, 1);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1OptionalHeadersEncoder_Encode(encoder, unknown);
+ assertTrue(length < 0, "Did not get error return when encoding unknown type");
+
+ CCNxCodecError *error = ccnxCodecTlvEncoder_GetError(encoder);
+ assertNotNull(error, "encoder did not set the error");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&unknown);
+}
+
+// ==================================================================================
+
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV0_OptionalHeadersEncoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_PacketDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_PacketDecoder.c
new file mode 100755
index 00000000..42d5be41
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_PacketDecoder.c
@@ -0,0 +1,684 @@
+/*
+ * 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.
+ */
+
+/**
+ * Decode whole packets then spot-check that fields from each section appear. We don't need
+ * to exhastively test here, as the individual decoders are exhaustively tested.
+ *
+ */
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnxCodecSchemaV1_PacketDecoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_zero_payload.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_no_payload.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_crc32c.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_bad_message_length.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_bad_validation_alg.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_validation_alg_overrun.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route_crc32c.h>
+
+#include "testrig_packetwrapper.c"
+
+#include <ccnx/common/internal/ccnx_ContentObjectFacadeV1.h>
+#include <ccnx/common/internal/ccnx_ValidationFacadeV1.h>
+
+// =========================================================================
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_PacketDecoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(ContentObject);
+ LONGBOW_RUN_TEST_FIXTURE(Control);
+ LONGBOW_RUN_TEST_FIXTURE(Interest);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_PacketDecoder)
+{
+ 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(ccnxCodecSchemaV1_PacketDecoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(ContentObject)
+{
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObject_RsaSha256_FixedHeader);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObject_RsaSha256_Name);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObject_RsaSha256_ExpiryTime);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObject_RsaSha256_ValidationAlg_KeyId);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObject_RsaSha256_ValidationPayload);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObject_zero_payload);
+ LONGBOW_RUN_TEST_CASE(ContentObject, ContentObject_no_payload);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(ContentObject)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(ContentObject)
+{
+ 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(ContentObject, ContentObject_RsaSha256_FixedHeader)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), 0, sizeof(v1_content_nameA_keyid1_rsasha256));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+
+ // leave the FixedHeader buffer at position 0
+ parcBuffer_Rewind(fixedHeader);
+
+ PARCBuffer *trueFixedHeader = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, 8, 0, 8);
+ assertTrue(parcBuffer_Equals(fixedHeader, trueFixedHeader), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueFixedHeader, 3);
+ printf("Got\n");
+ parcBuffer_Display(fixedHeader, 3);
+ }
+
+ parcBuffer_Release(&trueFixedHeader);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ContentObject_RsaSha256_Name)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256,
+ sizeof(v1_content_nameA_keyid1_rsasha256),
+ 0,
+ sizeof(v1_content_nameA_keyid1_rsasha256));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ CCNxName *name = ccnxTlvDictionary_GetName(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME);
+ CCNxName *trueName = ccnxName_CreateFromCString(v1_content_nameA_keyid1_rsasha256_URI);
+
+ assertTrue(ccnxName_Equals(name, trueName), "Buffers not equal")
+ {
+ printf("Expected\n");
+ ccnxName_Display(trueName, 3);
+ printf("Got\n");
+ ccnxName_Display(name, 3);
+ }
+
+ ccnxName_Release(&trueName);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ContentObject_RsaSha256_ExpiryTime)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), 0, sizeof(v1_content_nameA_keyid1_rsasha256));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ uint64_t expiryTime = ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_EXPIRY_TIME);
+
+ TlvExtent expiryExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_EXPIRY_TIME);
+
+ parcBuffer_SetPosition(packetBuffer, expiryExtent.offset);
+ uint64_t trueTime;
+ ccnxCodecTlvUtilities_GetVarInt(packetBuffer, expiryExtent.length, &trueTime);
+
+ assertTrue(expiryTime == trueTime, "Wrong time, expected %" PRIx64 " got %" PRIx64, trueTime, expiryTime);
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ContentObject_RsaSha256_ValidationAlg_KeyId)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), 0, sizeof(v1_content_nameA_keyid1_rsasha256));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *keyid = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID);
+
+ TlvExtent keyidExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_KEYID);
+ PARCBuffer *trueKeyid = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), keyidExtent.offset, keyidExtent.offset + keyidExtent.length);
+
+ assertTrue(parcBuffer_Equals(keyid, trueKeyid), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueKeyid, 3);
+ printf("Got\n");
+ parcBuffer_Display(keyid, 3);
+ }
+
+ parcBuffer_Release(&trueKeyid);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ContentObject_RsaSha256_ValidationPayload)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), 0, sizeof(v1_content_nameA_keyid1_rsasha256));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *validationPayload = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+
+ TlvExtent payloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_SIGBITS);
+ PARCBuffer *truePayload = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), payloadExtent.offset, payloadExtent.offset + payloadExtent.length);
+
+ assertTrue(parcBuffer_Equals(validationPayload, truePayload), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truePayload, 3);
+ printf("Got\n");
+ parcBuffer_Display(validationPayload, 3);
+ }
+
+ parcBuffer_Release(&truePayload);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ContentObject_zero_payload)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_content_zero_payload, sizeof(v1_content_zero_payload), 0, sizeof(v1_content_zero_payload));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ CCNxName *testName = CCNxContentObjectFacadeV1_Implementation.getName(dictionary);
+ assertNotNull(testName, "Got null name on decode");
+
+ PARCBuffer *testPayload = CCNxContentObjectFacadeV1_Implementation.getPayload(dictionary);
+ assertNotNull(testPayload, "got null payload")
+ assertTrue(parcBuffer_Remaining(testPayload) == 0, "Wrong length, expected 0 got %zu", parcBuffer_Remaining(testPayload));
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(ContentObject, ContentObject_no_payload)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_content_no_payload, sizeof(v1_content_no_payload), 0, sizeof(v1_content_no_payload));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ CCNxName *test = CCNxContentObjectFacadeV1_Implementation.getName(dictionary);
+ assertNotNull(test, "Got null name on decode");
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Control)
+{
+ LONGBOW_RUN_TEST_CASE(Control, CPIAddRoute_Crc32c_FixedHeader);
+ LONGBOW_RUN_TEST_CASE(Control, CPIAddRoute_Crc32c_Payload);
+ LONGBOW_RUN_TEST_CASE(Control, CPIAddRoute_Crc32c_ValidationAlg_CryptoSuite);
+ LONGBOW_RUN_TEST_CASE(Control, CPIAddRoute_Crc32c_ValidationPayload);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Control)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Control)
+{
+ 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(Control, CPIAddRoute_Crc32c_FixedHeader)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_cpi_add_route_crc32c, sizeof(v1_cpi_add_route_crc32c), 0, sizeof(v1_cpi_add_route_crc32c));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+
+ // leave the FixedHeader buffer at position 0
+ parcBuffer_Rewind(fixedHeader);
+
+ PARCBuffer *trueFixedHeader = parcBuffer_Wrap(v1_cpi_add_route_crc32c, 8, 0, 8);
+ assertTrue(parcBuffer_Equals(fixedHeader, trueFixedHeader), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueFixedHeader, 3);
+ printf("Got\n");
+ parcBuffer_Display(fixedHeader, 3);
+ }
+
+ parcBuffer_Release(&trueFixedHeader);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Control, CPIAddRoute_Crc32c_Payload)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_cpi_add_route_crc32c, sizeof(v1_cpi_add_route_crc32c), 0, sizeof(v1_cpi_add_route_crc32c));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+
+ TlvExtent validationPayloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_cpi_add_route_crc32c), V1_MANIFEST_CPI_SIGBITS);
+ PARCBuffer *trueValidationPayload = parcBuffer_Wrap(v1_cpi_add_route_crc32c, sizeof(v1_cpi_add_route_crc32c), validationPayloadExtent.offset, validationPayloadExtent.offset + validationPayloadExtent.length);
+
+ assertTrue(parcBuffer_Equals(test, trueValidationPayload), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueValidationPayload, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&trueValidationPayload);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Control, CPIAddRoute_Crc32c_ValidationAlg_CryptoSuite)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_cpi_add_route_crc32c, sizeof(v1_cpi_add_route_crc32c), 0, sizeof(v1_cpi_add_route_crc32c));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCCryptoSuite test = (PARCCryptoSuite) ccnxValidationFacadeV1_GetCryptoSuite(dictionary);
+ PARCCryptoSuite trueCryptoSuite = PARCCryptoSuite_NULL_CRC32C;
+
+ assertTrue(test == trueCryptoSuite, "Wrong crypto suite, expected %d got %d", trueCryptoSuite, test);
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Control, CPIAddRoute_Crc32c_ValidationPayload)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_cpi_add_route_crc32c, sizeof(v1_cpi_add_route_crc32c), 0, sizeof(v1_cpi_add_route_crc32c));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *validationPayload = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+
+ TlvExtent payloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_cpi_add_route_crc32c), V1_MANIFEST_CPI_SIGBITS);
+ PARCBuffer *truePayload = parcBuffer_Wrap(v1_cpi_add_route_crc32c, sizeof(v1_cpi_add_route_crc32c), payloadExtent.offset, payloadExtent.offset + payloadExtent.length);
+
+ assertTrue(parcBuffer_Equals(validationPayload, truePayload), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truePayload, 3);
+ printf("Got\n");
+ parcBuffer_Display(validationPayload, 3);
+ }
+
+ parcBuffer_Release(&truePayload);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Interest)
+{
+ LONGBOW_RUN_TEST_CASE(Interest, interest_bad_message_length);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_all_fields_FixedHeader);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_all_fields_Lifetime);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_all_fields_Name);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_all_fields_ValidationAlg_KeyId);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_all_fields_ValidationPayload);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_nameA_crc32c_ValidationAlg_CryptoSuite);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_nameA_crc32c_ValidationPayload);
+ LONGBOW_RUN_TEST_CASE(Interest, ccnxCodecSchemaV1PacketDecoder_BufferDecode);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_bad_validation_alg);
+ LONGBOW_RUN_TEST_CASE(Interest, interest_validation_alg_overrun);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Interest)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Interest)
+{
+ 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(Interest, interest_bad_message_length)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_bad_message_length, sizeof(v1_interest_bad_message_length), 0, sizeof(v1_interest_bad_message_length));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertFalse(success, "Should have seen and error on decode");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Error not set when bad decode");
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Interest, interest_all_fields_FixedHeader)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+
+ // leave the FixedHeader buffer at position 0
+ parcBuffer_Rewind(fixedHeader);
+
+ PARCBuffer *trueFixedHeader = parcBuffer_Wrap(v1_interest_all_fields, 8, 0, 8);
+ assertTrue(parcBuffer_Equals(fixedHeader, trueFixedHeader), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueFixedHeader, 3);
+ printf("Got\n");
+ parcBuffer_Display(fixedHeader, 3);
+ }
+
+ parcBuffer_Release(&trueFixedHeader);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Interest, interest_all_fields_Lifetime)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ uint64_t lifetime = ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime);
+
+ TlvExtent lifetimeExtent = getTruthTableHeaderExtent(TRUTHTABLENAME(v1_interest_all_fields), V1_MANIFEST_INT_LIFETIME);
+
+ parcBuffer_SetPosition(packetBuffer, lifetimeExtent.offset);
+ uint64_t trueTime;
+ ccnxCodecTlvUtilities_GetVarInt(packetBuffer, lifetimeExtent.length, &trueTime);
+
+ assertTrue(lifetime == trueTime, "Wrong time, expected %" PRIx64 " got %" PRIx64, trueTime, lifetime);
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Interest, interest_all_fields_Name)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ CCNxName *name = ccnxTlvDictionary_GetName(dictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME);
+ CCNxName *trueName = ccnxName_CreateFromCString(v1_interest_all_fields_URI);
+
+ assertTrue(ccnxName_Equals(name, trueName), "Buffers not equal")
+ {
+ printf("Expected\n");
+ ccnxName_Display(trueName, 3);
+ printf("Got\n");
+ ccnxName_Display(name, 3);
+ }
+
+ ccnxName_Release(&trueName);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+/*
+ * This packet does not have a validation section, so the test is that its missing
+ */
+LONGBOW_TEST_CASE(Interest, interest_all_fields_ValidationAlg_KeyId)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *keyid = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID);
+ assertNull(keyid, "Got a non-null keyid from a packet without one");
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+/*
+ * Packet does not have validation, test for missing
+ */
+LONGBOW_TEST_CASE(Interest, interest_all_fields_ValidationPayload)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *payload = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+ assertNull(payload, "Got a non-null validation payload from a packet without one");
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Interest, interest_nameA_crc32c_ValidationAlg_CryptoSuite)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), 0, sizeof(v1_interest_nameA_crc32c));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCCryptoSuite suite = (PARCCryptoSuite) ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE);
+ PARCCryptoSuite trueSuite = PARCCryptoSuite_NULL_CRC32C;
+
+ assertTrue(suite == trueSuite, "Wrong crypto suite, expected %d got %d", trueSuite, suite);
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Interest, interest_nameA_crc32c_ValidationPayload)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), 0, sizeof(v1_interest_nameA_crc32c));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertTrue(success, "Error on decode: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *validationPayload = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+
+ TlvExtent payloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_ValidationPayload);
+ PARCBuffer *truePayload = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), payloadExtent.offset, payloadExtent.offset + payloadExtent.length);
+
+ assertTrue(parcBuffer_Equals(validationPayload, truePayload), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truePayload, 3);
+ printf("Got\n");
+ parcBuffer_Display(validationPayload, 3);
+ }
+
+ parcBuffer_Release(&truePayload);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Interest, ccnxCodecSchemaV1PacketDecoder_BufferDecode)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), 0, sizeof(v1_interest_nameA_crc32c));
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_BufferDecode(packetBuffer, dictionary);
+ assertTrue(success, "Error on decode");
+
+ PARCBuffer *validationPayload = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+
+ TlvExtent payloadExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_ValidationPayload);
+ PARCBuffer *truePayload = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), payloadExtent.offset, payloadExtent.offset + payloadExtent.length);
+
+ assertTrue(parcBuffer_Equals(validationPayload, truePayload), "Buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truePayload, 3);
+ printf("Got\n");
+ parcBuffer_Display(validationPayload, 3);
+ }
+
+ parcBuffer_Release(&truePayload);
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Interest, interest_bad_validation_alg)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_bad_validation_alg, sizeof(v1_interest_bad_validation_alg), 0, sizeof(v1_interest_bad_validation_alg));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertFalse(success, "Should have seen and error on decode");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Error not set when bad decode");
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+LONGBOW_TEST_CASE(Interest, interest_validation_alg_overrun)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_validation_alg_overrun, sizeof(v1_interest_validation_alg_overrun), 0, sizeof(v1_interest_validation_alg_overrun));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(packetBuffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecSchemaV1PacketDecoder_Decode(decoder, dictionary);
+ assertFalse(success, "Should have seen and error on decode");
+
+ CCNxCodecError *error = ccnxCodecTlvDecoder_GetError(decoder);
+ assertNotNull(error, "Error not set when bad decode");
+
+ parcBuffer_Release(&packetBuffer);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+}
+
+// =========================================================================
+
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_PacketDecoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_PacketEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_PacketEncoder.c
new file mode 100755
index 00000000..eb79502e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_PacketEncoder.c
@@ -0,0 +1,1054 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_PacketEncoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_crc32c.h>
+
+#include "testrig_encoder.c"
+
+#include <ccnx/common/ccnx_Interest.h>
+#include <ccnx/common/ccnx_InterestReturn.h>
+#include <ccnx/common/ccnx_ContentObject.h>
+
+#include <ccnx/common/validation/ccnxValidation_CRC32C.h>
+
+
+// =========================================================================
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_PacketEncoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(ContentObject);
+ LONGBOW_RUN_TEST_FIXTURE(Interest);
+ LONGBOW_RUN_TEST_FIXTURE(InterestReturn);
+ LONGBOW_RUN_TEST_FIXTURE(Control);
+ LONGBOW_RUN_TEST_FIXTURE(UnknownType);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_PacketEncoder)
+{
+ 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(ccnxCodecSchemaV1_PacketEncoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(ContentObject)
+{
+ LONGBOW_RUN_TEST_CASE(ContentObject, v1_content_nameA_keyid1_rsasha256);
+ LONGBOW_RUN_TEST_CASE(ContentObject, zero_length_payload);
+ LONGBOW_RUN_TEST_CASE(ContentObject, null_payload);
+ LONGBOW_RUN_TEST_CASE(ContentObject, no_cryptosuite);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(ContentObject)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(ContentObject)
+{
+ 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;
+}
+
+/*
+ * Make a dictionary equivalent to v1_content_nameA_keyid1_rsasha256 and encode it then compare
+ */
+LONGBOW_TEST_CASE(ContentObject, v1_content_nameA_keyid1_rsasha256)
+{
+ CCNxName *name = ccnxName_CreateFromCString(v1_content_nameA_keyid1_rsasha256_URI);
+
+ TlvExtent payloadExtent =
+ getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_PAYLOAD);
+ PARCBuffer *payload = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256,
+ sizeof(v1_content_nameA_keyid1_rsasha256),
+ payloadExtent.offset,
+ payloadExtent.offset + payloadExtent.length);
+
+ CCNxTlvDictionary *message =
+ ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ name, CCNxPayloadType_KEY, payload);
+
+ TlvExtent fragmentExtent =
+ getTruthTableHeaderExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_E2EFRAG);
+ PARCBuffer *fragment = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256,
+ sizeof(v1_content_nameA_keyid1_rsasha256),
+ fragmentExtent.offset,
+ fragmentExtent.offset + fragmentExtent.length);
+ ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_OBJFRAG, fragment);
+
+ uint64_t expiryTime = 1388534400000ULL;
+ ccnxContentObject_SetExpiryTime(message, expiryTime);
+
+ uint64_t endChunkNumber = 0x06050403;
+ ccnxContentObject_SetFinalChunkNumber(message, endChunkNumber);
+
+ TlvExtent keyIdExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_KEYID);
+ PARCBuffer *keyid = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256,
+ sizeof(v1_content_nameA_keyid1_rsasha256),
+ keyIdExtent.offset,
+ keyIdExtent.offset + keyIdExtent.length);
+
+ TlvExtent keyExtent = getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_PUBKEY);
+ PARCBuffer *key = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256,
+ sizeof(v1_content_nameA_keyid1_rsasha256),
+ keyExtent.offset,
+ keyExtent.offset + keyExtent.length);
+
+ ccnxValidationFacadeV1_SetCryptoSuite(message, PARCCryptoSuite_RSA_SHA256);
+ ccnxValidationFacadeV1_SetKeyId(message, keyid);
+ ccnxValidationFacadeV1_SetPublicKey(message, key);
+
+ TlvExtent sigExtent =
+ getTruthTableExtent(TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256), V1_MANIFEST_OBJ_SIGBITS);
+ PARCBuffer *sig = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256,
+ sizeof(v1_content_nameA_keyid1_rsasha256),
+ sigExtent.offset,
+ sigExtent.offset + sigExtent.length);
+
+ ccnxValidationFacadeV1_SetPayload(message, sig);
+
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+ assertFalse(length < 0, "Got encoding error: %s",
+ ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+ assertTrue(length == sizeof(v1_content_nameA_keyid1_rsasha256),
+ "Wrong length, expected %zu got %zd", sizeof(v1_content_nameA_keyid1_rsasha256), length);
+
+ // verify
+ PARCBuffer *truth = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256,
+ sizeof(v1_content_nameA_keyid1_rsasha256),
+ 0,
+ sizeof(v1_content_nameA_keyid1_rsasha256));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+
+ uint8_t *truthOverlay = parcBuffer_Overlay(truth, 0);
+ uint8_t *testOverlay = parcBuffer_Overlay(test, 0);
+
+ for (ssize_t i = 0; i < length; i++) {
+ if (truthOverlay[i] != testOverlay[i]) {
+ printf("Buffers differ at byte %zd, expected 0x%02x got 0x%02x\n", i, truthOverlay[i], testOverlay[i]);
+ break;
+ }
+ }
+ }
+
+ // cleanup
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&sig);
+ parcBuffer_Release(&key);
+ parcBuffer_Release(&keyid);
+ parcBuffer_Release(&payload);
+ parcBuffer_Release(&fragment);
+ ccnxName_Release(&name);
+ ccnxTlvDictionary_Release(&message);
+}
+
+
+LONGBOW_TEST_CASE(ContentObject, zero_length_payload)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/no/payload");
+ PARCBuffer *payload = parcBuffer_Allocate(0);
+
+ CCNxTlvDictionary *message =
+ ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ name, CCNxPayloadType_DATA, payload);
+
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+ assertFalse(length < 0, "Got encoding error: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertNotNull(encoded, "got null output buffer");
+
+ parcBuffer_Display(encoded, 3);
+
+ parcBuffer_Release(&encoded);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&message);
+ parcBuffer_Release(&payload);
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(ContentObject, null_payload)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/no/payload");
+
+ CCNxTlvDictionary *message =
+ ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ name, CCNxPayloadType_DATA, NULL);
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+ assertFalse(length < 0, "Got encoding error: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertNotNull(encoded, "got null output buffer");
+
+ parcBuffer_Release(&encoded);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&message);
+ ccnxName_Release(&name);
+}
+
+/*
+ * A content object without a cryptosuite should not be signed
+ */
+LONGBOW_TEST_CASE(ContentObject, no_cryptosuite)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/no/payload");
+
+ CCNxTlvDictionary *message =
+ ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
+ name, CCNxPayloadType_DATA, NULL);
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+ assertFalse(length < 0, "Got encoding error: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *encoded = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertNotNull(encoded, "got null output buffer");
+
+ // it should be 33 bytes without a signature
+ assertTrue(parcBuffer_Remaining(encoded) == 33, "Wrong length exepcted 33 got %zu", parcBuffer_Remaining(encoded));
+
+ parcBuffer_Release(&encoded);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&message);
+ ccnxName_Release(&name);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Interest)
+{
+ LONGBOW_RUN_TEST_CASE(Interest, v1_interest_nameA_crc32c);
+ LONGBOW_RUN_TEST_CASE(Interest, v1_interest_nameA_crc32c_IoVec);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Interest)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Interest)
+{
+ 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;
+}
+
+/*
+ * Make an interest equivalent to v1_interest_nameA_crc32c and encode it
+ */
+LONGBOW_TEST_CASE(Interest, v1_interest_nameA_crc32c)
+{
+ CCNxName *name = ccnxName_CreateFromCString(v1_interest_nameA_crc32c_URI);
+
+ CCNxTlvDictionary *message =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ name, CCNxInterestDefault_LifetimeMilliseconds, NULL, NULL, 32);
+
+ TlvExtent fragmentExtent = getTruthTableHeaderExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_E2EFRAG);
+ PARCBuffer *fragment = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), fragmentExtent.offset, fragmentExtent.offset + fragmentExtent.length);
+ ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG, fragment);
+
+ ccnxValidationFacadeV1_SetCryptoSuite(message, PARCCryptoSuite_NULL_CRC32C);
+
+ TlvExtent sigExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_ValidationPayload);
+ PARCBuffer *sig = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), sigExtent.offset, sigExtent.offset + sigExtent.length);
+
+ ccnxValidationFacadeV1_SetPayload(message, sig);
+
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+ assertFalse(length < 0, "Got encoding error: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+ assertTrue(length == sizeof(v1_interest_nameA_crc32c), "Wrong length, expected %zu got %zd", sizeof(v1_interest_nameA_crc32c), length);
+
+ // verify
+ PARCBuffer *truth = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), 0, sizeof(v1_interest_nameA_crc32c));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+
+ uint8_t *truthOverlay = parcBuffer_Overlay(truth, 0);
+ uint8_t *testOverlay = parcBuffer_Overlay(test, 0);
+
+ for (ssize_t i = 0; i < length; i++) {
+ if (truthOverlay[i] != testOverlay[i]) {
+ printf("Buffers differ at byte %zd, expected 0x%02x got 0x%02x", i, truthOverlay[i], testOverlay[i]);
+ break;
+ }
+ }
+ }
+
+ // cleanup
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&sig);
+ parcBuffer_Release(&fragment);
+ ccnxName_Release(&name);
+ ccnxTlvDictionary_Release(&message);
+}
+
+/*
+ * Make an interest equivalent to v1_interest_nameA_crc32c and encode it
+ */
+LONGBOW_TEST_CASE(Interest, v1_interest_nameA_crc32c_IoVec)
+{
+ CCNxName *name = ccnxName_CreateFromCString(v1_interest_nameA_crc32c_URI);
+
+ CCNxTlvDictionary *message =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ name, CCNxInterestDefault_LifetimeMilliseconds, NULL, NULL, 32);
+
+ TlvExtent fragmentExtent = getTruthTableHeaderExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_E2EFRAG);
+ PARCBuffer *fragment = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), fragmentExtent.offset, fragmentExtent.offset + fragmentExtent.length);
+ ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG, fragment);
+
+ ccnxValidationFacadeV1_SetCryptoSuite(message, PARCCryptoSuite_NULL_CRC32C);
+
+ TlvExtent sigExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_ValidationPayload);
+ PARCBuffer *sig = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), sigExtent.offset, sigExtent.offset + sigExtent.length);
+
+ ccnxValidationFacadeV1_SetPayload(message, sig);
+
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecSchemaV1PacketEncoder_DictionaryEncode(message, NULL);
+ assertNotNull(iovec, "Got null iovec from ccnxCodecSchemaV1PacketEncoder_DictionaryEncode");
+
+ size_t length = ccnxCodecNetworkBufferIoVec_Length(iovec);
+ assertTrue(length == sizeof(v1_interest_nameA_crc32c), "Wrong length, expected %zu got %zd", sizeof(v1_interest_nameA_crc32c), length);
+
+ // verify
+ PARCBuffer *truth = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), 0, sizeof(v1_interest_nameA_crc32c));
+
+ int iovecCount = ccnxCodecNetworkBufferIoVec_GetCount(iovec);
+ PARCBuffer *test = parcBuffer_Allocate(length);
+ const struct iovec *array = ccnxCodecNetworkBufferIoVec_GetArray(iovec);
+ for (int i = 0; i < iovecCount; i++) {
+ parcBuffer_PutArray(test, array[i].iov_len, array[i].iov_base);
+ }
+ parcBuffer_Flip(test);
+
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+
+ uint8_t *truthOverlay = parcBuffer_Overlay(truth, 0);
+ uint8_t *testOverlay = parcBuffer_Overlay(test, 0);
+
+ for (ssize_t i = 0; i < length; i++) {
+ if (truthOverlay[i] != testOverlay[i]) {
+ printf("Buffers differ at byte %zd, expected 0x%02x got 0x%02x", i, truthOverlay[i], testOverlay[i]);
+ break;
+ }
+ }
+ }
+
+ // cleanup
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&sig);
+ parcBuffer_Release(&fragment);
+ ccnxName_Release(&name);
+ ccnxTlvDictionary_Release(&message);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(InterestReturn)
+{
+ LONGBOW_RUN_TEST_CASE(InterestReturn, v1_interest_return);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(InterestReturn)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(InterestReturn)
+{
+ 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;
+}
+
+/*
+ * Make an interest return and encode it
+ */
+LONGBOW_TEST_CASE(InterestReturn, v1_interest_return)
+{
+ CCNxName *name = ccnxName_CreateFromCString(v1_interest_nameA_crc32c_URI);
+
+ CCNxInterest *interest =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ name, CCNxInterestDefault_LifetimeMilliseconds, NULL, NULL, 32);
+ ccnxName_Release(&name);
+
+ TlvExtent fragmentExtent = getTruthTableHeaderExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_E2EFRAG);
+ PARCBuffer *fragment = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), fragmentExtent.offset, fragmentExtent.offset + fragmentExtent.length);
+ ccnxTlvDictionary_PutBuffer(interest, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG, fragment);
+ parcBuffer_Release(&fragment);
+
+ ccnxValidationFacadeV1_SetCryptoSuite(interest, PARCCryptoSuite_NULL_CRC32C);
+
+ TlvExtent sigExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_ValidationPayload);
+ PARCBuffer *sig = parcBuffer_Wrap(v1_interest_nameA_crc32c, sizeof(v1_interest_nameA_crc32c), sigExtent.offset, sigExtent.offset + sigExtent.length);
+
+ ccnxValidationFacadeV1_SetPayload(interest, sig);
+ parcBuffer_Release(&sig);
+
+ CCNxTlvDictionary *message =
+ ccnxInterestReturn_Create(interest, CCNxInterestReturn_ReturnCode_NoResources);
+ ccnxInterest_Release(&interest);
+
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+ ssize_t expectedLength = sizeof(v1_interest_nameA_crc32c);
+ assertFalse(length < 0, "Got encoding error: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+ assertTrue(length == expectedLength, "Wrong length, expected %zu got %zd", expectedLength, length);
+
+ // verify
+ PARCBuffer *truth = parcBuffer_Wrap(v1_interest_nameA_crc32c_returned, sizeof(v1_interest_nameA_crc32c_returned), 0, sizeof(v1_interest_nameA_crc32c_returned));
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+
+ uint8_t *truthOverlay = parcBuffer_Overlay(truth, 0);
+ uint8_t *testOverlay = parcBuffer_Overlay(test, 0);
+
+ for (ssize_t i = 0; i < length; i++) {
+ if (truthOverlay[i] != testOverlay[i]) {
+ printf("Buffers differ at byte %zd, expected 0x%02x got 0x%02x\n", i, truthOverlay[i], testOverlay[i]);
+ }
+ }
+ }
+
+ // cleanup
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&message);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Control)
+{
+ LONGBOW_RUN_TEST_CASE(Control, payload);
+ LONGBOW_RUN_TEST_CASE(Control, cryptosuite);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Control)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Control)
+{
+ 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(Control, payload)
+{
+ uint8_t encoded[] = {
+ 0x01, 0xa4, 0x00, 0x22,
+ 0x00, 0x00, 0x00, 0x08,
+
+ 0xbe, 0xef, 0x00, 0x16, // control message
+
+ 0x7b, 0x22, 0x74, 0x68, // {"th
+ 0x69, 0x73, 0x20, 0x69, // is i
+ 0x73, 0x22, 0x3a, 0x22, // s":"
+ 0x61, 0x6e, 0x6e, 0x6f, // anno
+ 0x79, 0x69, 0x6e, 0x67, // ying
+ 0x22, 0x7d // "}
+ };
+
+
+ CCNxTlvDictionary *message = ccnxCodecSchemaV1TlvDictionary_CreateControl();
+
+ PARCJSON *json = parcJSON_Create();
+ parcJSON_AddString(json, "this is", "annoying");
+
+ ccnxTlvDictionary_PutJson(message, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, json);
+ parcJSON_Release(&json);
+
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+
+ assertFalse(length < 0, "Got encoding error: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ // verify
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+
+ uint8_t *truthOverlay = parcBuffer_Overlay(truth, 0);
+ uint8_t *testOverlay = parcBuffer_Overlay(test, 0);
+
+ for (ssize_t i = 0; i < length; i++) {
+ if (truthOverlay[i] != testOverlay[i]) {
+ printf("Buffers differ at byte %zd, expected 0x%02x got 0x%02x", i, truthOverlay[i], testOverlay[i]);
+ break;
+ }
+ }
+ }
+
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&message);
+ parcBuffer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Control, cryptosuite)
+{
+ uint8_t encoded[] = {
+ 0x01, 0xA4, 0x00, 16,
+ 0x00, 0x00, 0x00, 8,
+ 0xBE, 0xEF, 0x00, 4,
+ 'a', 'b', 'c', 'd',
+ 0x00, 0x03, 0x00, 4,
+ 0x00, 0x02, 0x00, 0
+ };
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ PARCBuffer *payload = parcBuffer_Wrap(encoded, sizeof(encoded), 12, 16);
+
+ CCNxTlvDictionary *message = ccnxCodecSchemaV1TlvDictionary_CreateControl();
+ ccnxTlvDictionary_PutBuffer(message, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, payload);
+ ccnxValidationCRC32C_Set(message);
+
+ ccnxValidationCRC32C_Set(message);
+
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ PARCSigner *signer = ccnxValidationCRC32C_CreateSigner();
+ ccnxCodecTlvEncoder_SetSigner(encoder, signer);
+
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+ assertFalse(length < 0, "Got encoding error: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertNotNull(test, "Got null buffer from encoder");
+ uint8_t testSuite = parcBuffer_GetAtIndex(test, 21);
+ assertTrue(testSuite == 2, "Wrong cryptosuite, expected 2 got %u", testSuite);
+
+ parcSigner_Release(&signer);
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&message);
+ parcBuffer_Release(&payload);
+ parcBuffer_Release(&truth);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(UnknownType)
+{
+ LONGBOW_RUN_TEST_CASE(UnknownType, unknown);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(UnknownType)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(UnknownType)
+{
+ 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;
+}
+
+/*
+ * try to encode a message with unknown message type
+ */
+LONGBOW_TEST_CASE(UnknownType, unknown)
+{
+ // this initializes the dictionary to unknown type
+ CCNxTlvDictionary *message = ccnxTlvDictionary_Create(20, 20);
+
+ // encode
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = ccnxCodecSchemaV1PacketEncoder_Encode(encoder, message);
+ assertTrue(length < 0, "Did not get error condition for unknown type");
+
+ CCNxCodecError *error = ccnxCodecTlvEncoder_GetError(encoder);
+ assertNotNull(error, "Did not get an error for invalid encoding");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ ccnxTlvDictionary_Release(&message);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _getHopLimit_Present);
+ LONGBOW_RUN_TEST_CASE(Local, _getHopLimit_Missing);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeFixedHeader_ContentObject);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeFixedHeader_Interest);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeOptionalHeaders);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeMessage_Interest);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeMessage_ContentObject);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeCPI);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeMessage_Unknown);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeValidationAlg_Present);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeValidationAlg_Missing);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeValidationPayload_Present);
+ LONGBOW_RUN_TEST_CASE(Local, _encodeValidationPayload_Missing);
+}
+
+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, _getHopLimit_Present)
+{
+ uint8_t hoplimit = 77;
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxTlvDictionary_PutInteger(dict, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT, hoplimit);
+
+ uint8_t test = _getHopLimit(dict);
+ assertTrue(test == hoplimit, "Got wrong hoplimit, expected %u got %u", hoplimit, test);
+ ccnxTlvDictionary_Release(&dict);
+}
+
+LONGBOW_TEST_CASE(Local, _getHopLimit_Missing)
+{
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ uint8_t test = _getHopLimit(dict);
+ assertTrue(test == CCNxInterestDefault_HopLimit, "Got wrong hoplimit, expected %u got %u", CCNxInterestDefault_HopLimit, test);
+ ccnxTlvDictionary_Release(&dict);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeFixedHeader_ContentObject)
+{
+ uint8_t encoded[] = {
+ 0x01, 0x01, 0x00, 100, // ver = 1, type = content object, length = 100
+ 0x00, 0x00, 0x00, 14, // reserved = 0x0000000, header length = 14
+ };
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = _encodeFixedHeader(encoder, dict, CCNxCodecSchemaV1Types_PacketType_ContentObject, 14, 100);
+ assertTrue(length == 8, "wrong length, expected %d got %zd", 8, length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeFixedHeader_Interest)
+{
+ uint8_t encoded[] = {
+ 0x01, 0x00, 0x00, 100, // ver = 1, type = interest, length = 100
+ 0x1f, 0x00, 0x00, 14, // hoplimit = 31, reserved = 0x0000, header length = 14
+ };
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxTlvDictionary_PutInteger(dict, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT, 31);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = _encodeFixedHeader(encoder, dict, CCNxCodecSchemaV1Types_PacketType_Interest, 14, 100);
+ assertTrue(length == 8, "wrong length, expected %d got %zd", 8, length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeOptionalHeaders)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x01, 0x00, 2, // Interest Lifetime (2 bytes)
+ 0xEA, 0xEB,
+ };
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxTlvDictionary_PutInteger(dict, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime, 0xEAEB);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ssize_t length = _encodeOptionalHeaders(encoder, dict);
+ assertTrue(length == sizeof(encoded), "wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeMessage_Interest)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x01, 0x00, 13,
+ 0x00, 0x00, 0x00, 9,
+ 0x00, CCNxNameLabelType_NAME, 0x00, 5,
+ 'p', 'o', 'p', 'p', 'y'
+ };
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxName *name = ccnxName_CreateFromCString("lci:/poppy");
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxTlvDictionary_PutName(dict, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME, name);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxCodecSchemaV1Types_PacketType packetType;
+ ssize_t length = _encodeMessage(encoder, dict, &packetType);
+ assertTrue(length == sizeof(encoded), "wrong length, expected %zu got %zd", sizeof(encoded), length);
+ assertTrue(packetType == CCNxCodecSchemaV1Types_PacketType_Interest, "Wrong packet type, expected %d got %d",
+ CCNxCodecSchemaV1Types_PacketType_Interest, packetType);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxName_Release(&name);
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeMessage_ContentObject)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x02, 0x00, 13,
+ 0x00, 0x00, 0x00, 9,
+ 0x00, CCNxNameLabelType_NAME, 0x00, 5,
+ 'p', 'o', 'p', 'p', 'y'
+ };
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxName *name = ccnxName_CreateFromCString("lci:/poppy");
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxTlvDictionary_PutName(dict, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME, name);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxCodecSchemaV1Types_PacketType packetType;
+ ssize_t length = _encodeMessage(encoder, dict, &packetType);
+ assertTrue(length == sizeof(encoded), "wrong length, expected %zu got %zd", sizeof(encoded), length);
+ assertTrue(packetType == CCNxCodecSchemaV1Types_PacketType_ContentObject, "Wrong packet type, expected %d got %d",
+ CCNxCodecSchemaV1Types_PacketType_ContentObject, packetType);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxName_Release(&name);
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeCPI)
+{
+ uint8_t encoded [] = {
+ 0x00, 0x02, 0x03, 0x99, //
+ };
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxValidationCRC32C_Set(dict);
+ ccnxTlvDictionary_PutBuffer(dict, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD, truth);
+
+ ssize_t length = _encodeCPI(encoder, dict);
+ assertTrue(length == sizeof(encoded), "wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+/*
+ * This test requires that we set the message type to some unknown value, which we get if
+ * we create a dictionary with ccnxTlvDictionary_Create() and dont call anything to set
+ * the message type. It will be "CCNxTlvDictionary_Unknown".
+ */
+LONGBOW_TEST_CASE(Local, _encodeMessage_Unknown)
+{
+ CCNxTlvDictionary *dict = ccnxTlvDictionary_Create(20, 20);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxCodecSchemaV1Types_PacketType packetType;
+ ssize_t length = _encodeMessage(encoder, dict, &packetType);
+ assertTrue(length < 0, "wrong length, expected negative got %zd", length);
+
+ CCNxCodecError *error = ccnxCodecTlvEncoder_GetError(encoder);
+ assertNotNull(error, "Got null error when an error condition should have been set");
+
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeValidationAlg_Present)
+{
+ uint8_t encoded [] = {
+ 0x00, 0x03, 0x00, 4, // validation alg, length = 4
+ 0x00, 0x02, 0x00, 0x00, // CRC32C
+ };
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ PARCBuffer *truePayload = parcBuffer_Wrap(encoded, sizeof(encoded), 4, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxValidationCRC32C_Set(dict);
+ ccnxTlvDictionary_PutBuffer(dict, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD, truePayload);
+
+ ssize_t length = _encodeValidationAlg(encoder, dict);
+ assertTrue(length == sizeof(encoded), "wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&truePayload);
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeValidationAlg_Missing)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ssize_t length = _encodeValidationAlg(encoder, dict);
+ assertTrue(length == 0, "wrong length, expected %d got %zd", 0, length);
+
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeValidationPayload_Present)
+{
+ uint8_t encoded [] = {
+ 0x00, 0x04, 0x00, 4, // validation payload, length = 4
+ 0x00, 0x02, 0x03, 0x99, //
+ };
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ PARCBuffer *truePayload = parcBuffer_Wrap(encoded, sizeof(encoded), 4, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ ccnxValidationCRC32C_Set(dict);
+ ccnxTlvDictionary_PutBuffer(dict, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD, truePayload);
+
+ ssize_t length = _encodeValidationPayload(encoder, dict);
+ assertTrue(length == sizeof(encoded), "wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&truePayload);
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Local, _encodeValidationPayload_Missing)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+
+ ssize_t length = _encodeValidationPayload(encoder, dict);
+ assertTrue(length == 0, "wrong length, expected %d got %zd", 0, length);
+
+ ccnxTlvDictionary_Release(&dict);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+
+// ==================================================================================
+
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_PacketEncoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_TlvDictionary.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_TlvDictionary.c
new file mode 100755
index 00000000..ccaa8b13
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_TlvDictionary.c
@@ -0,0 +1,118 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_TlvDictionary.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_TlvDictionary)
+{
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_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(ccnxCodecSchemaV1_TlvDictionary)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1TlvDictionary_CreateInterest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1TlvDictionary_CreateInterestReturn);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1TlvDictionary_CreateContentObject);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecSchemaV1TlvDictionary_CreateControl);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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, ccnxCodecSchemaV1TlvDictionary_CreateInterest)
+{
+ CCNxTlvDictionary *test = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ assertNotNull(test, "Got null return from ccnxCodecSchemaV1TlvDictionary_CreateInterest");
+ assertTrue(ccnxTlvDictionary_IsInterest(test), "Dictionary is not an interest");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema version, expected %d got %d",
+ CCNxTlvDictionary_SchemaVersion_V1,
+ ccnxTlvDictionary_GetSchemaVersion(test));
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1TlvDictionary_CreateInterestReturn)
+{
+ CCNxTlvDictionary *test = ccnxCodecSchemaV1TlvDictionary_CreateInterestReturn();
+ assertNotNull(test, "Got null return from ccnxCodecSchemaV1TlvDictionary_CreateInterest");
+ assertTrue(ccnxTlvDictionary_IsInterestReturn(test), "Dictionary is not an interest");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema version, expected %d got %d",
+ CCNxTlvDictionary_SchemaVersion_V1,
+ ccnxTlvDictionary_GetSchemaVersion(test));
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1TlvDictionary_CreateContentObject)
+{
+ CCNxTlvDictionary *test = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ assertNotNull(test, "Got null return from ccnxCodecSchemaV1TlvDictionary_CreateContentObject");
+ assertTrue(ccnxTlvDictionary_IsContentObject(test), "Dictionary is not a content object");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema version, expected %d got %d",
+ CCNxTlvDictionary_SchemaVersion_V1,
+ ccnxTlvDictionary_GetSchemaVersion(test));
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1TlvDictionary_CreateControl)
+{
+ CCNxTlvDictionary *test = ccnxCodecSchemaV1TlvDictionary_CreateControl();
+ assertNotNull(test, "Got null return from ccnxCodecSchemaV1TlvDictionary_CreateControl");
+ assertTrue(ccnxTlvDictionary_IsControl(test), "Dictionary is not a control");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema version, expected %d got %d",
+ CCNxTlvDictionary_SchemaVersion_V1,
+ ccnxTlvDictionary_GetSchemaVersion(test));
+ ccnxTlvDictionary_Release(&test);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_TlvDictionary);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ValidationDecoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ValidationDecoder.c
new file mode 100755
index 00000000..82cf69d1
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ValidationDecoder.c
@@ -0,0 +1,450 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_ValidationDecoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h>
+
+#include "testrig_packetwrapper.c"
+
+// =========================================================================
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_ValidationDecoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(DecodeAlg);
+ LONGBOW_RUN_TEST_FIXTURE(DecodePayload);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_ValidationDecoder)
+{
+ 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(ccnxCodecSchemaV1_ValidationDecoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(DecodeAlg)
+{
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, CRC32C);
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, HMAC_SHA256);
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, RSA_SHA256);
+
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, Cert);
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, PublicKey);
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, KeyId);
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, KeyName);
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, SigTime);
+
+ LONGBOW_RUN_TEST_CASE(DecodeAlg, KeyName_Invalid);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(DecodeAlg)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(DecodeAlg)
+{
+ 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(DecodeAlg, CRC32C)
+{
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvSuite = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C;
+ PARCCryptoSuite parcSuite = PARCCryptoSuite_NULL_CRC32C;
+
+ uint8_t encoded[] = {
+ 0x00, tlvSuite, 0x00, 0,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertTrue(success, "Failed ccnxCodecSchemaV1ValidationDecoder_DecodeAlg: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCCryptoSuite test = (PARCCryptoSuite) ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE);
+ assertTrue(test == parcSuite, "Got wrong suite, expected %d got %d", parcSuite, test);
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodeAlg, HMAC_SHA256)
+{
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvSuite = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256;
+ PARCCryptoSuite parcSuite = PARCCryptoSuite_HMAC_SHA256;
+
+ uint8_t encoded[] = {
+ 0x00, tlvSuite, 0x00, 0,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertTrue(success, "Failed ccnxCodecSchemaV1ValidationDecoder_DecodeAlg: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCCryptoSuite test = (PARCCryptoSuite) ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE);
+ assertTrue(test == parcSuite, "Got wrong suite, expected %d got %d", parcSuite, test);
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodeAlg, RSA_SHA256)
+{
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvSuite = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256;
+ PARCCryptoSuite parcSuite = PARCCryptoSuite_RSA_SHA256;
+
+ uint8_t encoded[] = {
+ 0x00, tlvSuite, 0x00, 0,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertTrue(success, "Failed ccnxCodecSchemaV1ValidationDecoder_DecodeAlg: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCCryptoSuite test = (PARCCryptoSuite) ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE);
+ assertTrue(test == parcSuite, "Got wrong suite, expected %d got %d", parcSuite, test);
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodeAlg, Cert)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x06, 0x00, 10,
+ 0x00, 0x0C, 0x00, 6,
+ 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertTrue(success, "Failed ccnxCodecSchemaV1ValidationDecoder_DecodeAlg: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 8, sizeof(encoded));
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CERT);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodeAlg, PublicKey)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x06, 0x00, 10,
+ 0x00, 0x0B, 0x00, 6,
+ 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertTrue(success, "Failed ccnxCodecSchemaV1ValidationDecoder_DecodeAlg: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 8, sizeof(encoded));
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodeAlg, KeyId)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x06, 0x00, 10,
+ 0x00, 0x09, 0x00, 6,
+ 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertTrue(success, "Failed ccnxCodecSchemaV1ValidationDecoder_DecodeAlg: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 8, sizeof(encoded));
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodeAlg, KeyName)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x06, 0x00, 44,
+ 0x00, 0x0E, 0x00, 40,
+ // --- name
+ 0x00, 0x00, 0x00, 16,
+ 0x00, 0x03, 0x00, 5,
+ 'a', 'p', 'p', 'l',
+ 'e',
+ 0x00, 0x03, 0x00, 3,
+ 'p', 'i', 'e',
+ // --- keyid
+ 0x00, 0x01, 0x00, 4,
+ 0xa1, 0xa2, 0xa3, 0xa4,
+ // --- hash
+ 0x00, 0x02, 0x00, 8,
+ 0xb1, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxName *name = ccnxName_CreateFromCString("lci:/3=apple/3=pie");
+ PARCBuffer *keyid = parcBuffer_Wrap(encoded, sizeof(encoded), 32, 36);
+ PARCBuffer *hash = parcBuffer_Wrap(encoded, sizeof(encoded), 40, 48);
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertTrue(success, "Failed ccnxCodecSchemaV1ValidationDecoder_DecodeAlg: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ // now test the 3 decoded fields
+ CCNxName *testName = ccnxTlvDictionary_GetName(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME);
+ assertTrue(ccnxName_Equals(testName, name), "keynames do not match")
+ {
+ 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), "keyid do not match")
+ {
+ 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), "keyid do not match")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(hash, 3);
+ printf("Got\n");
+ parcBuffer_Display(testHash, 3);
+ }
+
+ parcBuffer_Release(&keyid);
+ parcBuffer_Release(&hash);
+ ccnxName_Release(&name);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodeAlg, KeyName_Invalid)
+{
+ // link is missing the Name
+ uint8_t encoded[] = {
+ 0x00, 0x06, 0x00, 24,
+ 0x00, 0x0E, 0x00, 20,
+ // --- keyid
+ 0x00, 0x01, 0x00, 4,
+ 0xa1, 0xa2, 0xa3, 0xa4,
+ // --- hash
+ 0x00, 0x02, 0x00, 8,
+ 0xb1, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertFalse(success, "Should have failed decode as keyname is invalid");
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodeAlg, SigTime)
+{
+ uint64_t sigtime = 0x1122334455667788ULL;
+ uint8_t encoded[] = {
+ 0x00, 0x06, 0x00, 12,
+ 0x00, 0x0F, 0x00, 8,
+ 0x11, 0x22, 0x33, 0x44,
+ 0x55, 0x66, 0x77, 0x88
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodeAlg(decoder, dictionary);
+ assertTrue(success, "Failed ccnxCodecSchemaV1ValidationDecoder_DecodeAlg: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ uint64_t test = ccnxTlvDictionary_GetInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME);
+ assertTrue(test == sigtime, "Wrong sig time, expected %" PRIx64 ", got %" PRIx64, sigtime, test);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(DecodePayload)
+{
+ LONGBOW_RUN_TEST_CASE(DecodePayload, payload);
+ LONGBOW_RUN_TEST_CASE(DecodePayload, payload_zero);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(DecodePayload)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(DecodePayload)
+{
+ 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(DecodePayload, payload)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x04, 0x00, 8,
+ 0x11, 0x22, 0x33, 0x44,
+ 0x55, 0x66, 0x77, 0x88
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+
+ // the caller has already parsed the T and L, so we point to just payload
+ ccnxCodecTlvDecoder_Advance(decoder, 4);
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodePayload(decoder, dictionary);
+ assertTrue(success, "Failed to decode a valid payload: %s", ccnxCodecError_ToString(ccnxCodecTlvDecoder_GetError(decoder)));
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 4, 12);
+ PARCBuffer *test = ccnxTlvDictionary_GetBuffer(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(DecodePayload, payload_zero)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x04, 0x00, 0,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+
+ // the caller has already parsed the T and L, so we point to just payload
+ ccnxCodecTlvDecoder_Advance(decoder, 4);
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ bool success = ccnxCodecSchemaV1ValidationDecoder_DecodePayload(decoder, dictionary);
+ assertFalse(success, "Should have failed on 0-length payload");
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+// =========================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_ValidationDecoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ValidationEncoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ValidationEncoder.c
new file mode 100755
index 00000000..8a4d951a
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/test_ccnxCodecSchemaV1_ValidationEncoder.c
@@ -0,0 +1,565 @@
+/*
+ * 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 "../ccnxCodecSchemaV1_ValidationEncoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_crc32c.h>
+
+#include "testrig_packetwrapper.c"
+
+#include <ccnx/common/internal/ccnx_ValidationFacadeV1.h>
+
+#include <ccnx/common/validation/ccnxValidation_CRC32C.h>
+#include <ccnx/common/validation/ccnxValidation_HmacSha256.h>
+
+// =========================================================================
+
+LONGBOW_TEST_RUNNER(ccnxCodecSchemaV1_ValidationDecoder)
+{
+ LONGBOW_RUN_TEST_FIXTURE(EncodeAlg);
+ LONGBOW_RUN_TEST_FIXTURE(EncodePayload);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodecSchemaV1_ValidationDecoder)
+{
+ 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(ccnxCodecSchemaV1_ValidationDecoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(EncodeAlg)
+{
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, CRC32C);
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, HMAC_SHA256);
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, RSA_SHA256);
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, DeduceFromSigner);
+
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, _encodeCertificate);
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, _encodePublicKey);
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, _encodeKeyId);
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, _encodeKeyName);
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, _encodeSignatureTime_Specified);
+ LONGBOW_RUN_TEST_CASE(EncodeAlg, _encodeSignatureTime_Generated);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(EncodeAlg)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(EncodeAlg)
+{
+ 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(EncodeAlg, CRC32C)
+{
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvSuite = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C;
+ PARCCryptoSuite suite = PARCCryptoSuite_NULL_CRC32C;
+
+ uint8_t encoded[] = {
+ 0x00, tlvSuite, 0x00, 0,
+ };
+
+ PARCBuffer *trueEncoded = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxTlvDictionary_PutInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE, suite);
+
+ ssize_t length = ccnxCodecSchemaV1ValidationEncoder_EncodeAlg(encoder, dictionary);
+ assertFalse(length < 0, "Error on encoding: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(trueEncoded, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueEncoded, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&trueEncoded);
+}
+
+LONGBOW_TEST_CASE(EncodeAlg, HMAC_SHA256)
+{
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvSuite = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_HmacSha256;
+ PARCCryptoSuite suite = PARCCryptoSuite_HMAC_SHA256;
+
+ uint8_t encoded[] = {
+ 0x00, tlvSuite, 0x00, 0,
+ };
+
+ PARCBuffer *trueEncoded = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxTlvDictionary_PutInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE, suite);
+
+ ssize_t length = ccnxCodecSchemaV1ValidationEncoder_EncodeAlg(encoder, dictionary);
+ assertFalse(length < 0, "Error on encoding: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(trueEncoded, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueEncoded, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&trueEncoded);
+}
+
+LONGBOW_TEST_CASE(EncodeAlg, RSA_SHA256)
+{
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvSuite = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_RsaSha256;
+ PARCCryptoSuite suite = PARCCryptoSuite_RSA_SHA256;
+
+ uint8_t encoded[] = {
+ 0x00, tlvSuite, 0x00, 0,
+ };
+
+ PARCBuffer *trueEncoded = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxTlvDictionary_PutInteger(dictionary, CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE, suite);
+
+ ssize_t length = ccnxCodecSchemaV1ValidationEncoder_EncodeAlg(encoder, dictionary);
+ assertFalse(length < 0, "Error on encoding: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(trueEncoded, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueEncoded, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&trueEncoded);
+}
+
+LONGBOW_TEST_CASE(EncodeAlg, DeduceFromSigner)
+{
+ PARCSigner *signer = ccnxValidationCRC32C_CreateSigner();
+ CCNxCodecSchemaV1TlvDictionary_CryptoSuite tlvsuite = CCNxCodecSchemaV1TlvDictionary_CryptoSuite_CRC32C;
+
+ uint8_t encoded[] = {
+ 0x00, tlvsuite, 0x00, 0,
+ };
+
+ PARCBuffer *trueEncoded = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_SetSigner(encoder, signer);
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+
+ ssize_t length = ccnxCodecSchemaV1ValidationEncoder_EncodeAlg(encoder, dictionary);
+ assertFalse(length < 0, "Error on encoding: %s", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(trueEncoded, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(trueEncoded, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&trueEncoded);
+ parcSigner_Release(&signer);
+}
+
+// =======
+
+LONGBOW_TEST_CASE(EncodeAlg, _encodeCertificate)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x0C, 0x00, 6,
+ 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f
+ };
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ PARCBuffer *cert = parcBuffer_Wrap(encoded, sizeof(encoded), 4, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxValidationFacadeV1_SetCertificate(dictionary, cert);
+
+ ssize_t length = _encodeCertificate(encoder, dictionary);
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&cert);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+
+LONGBOW_TEST_CASE(EncodeAlg, _encodePublicKey)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x0B, 0x00, 6,
+ 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f
+ };
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ PARCBuffer *key = parcBuffer_Wrap(encoded, sizeof(encoded), 4, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxValidationFacadeV1_SetPublicKey(dictionary, key);
+
+ ssize_t length = _encodePublicKey(encoder, dictionary);
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&key);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(EncodeAlg, _encodeKeyId)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x09, 0x00, 6,
+ 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f
+ };
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ PARCBuffer *keyid = parcBuffer_Wrap(encoded, sizeof(encoded), 4, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxValidationFacadeV1_SetKeyId(dictionary, keyid);
+
+ ssize_t length = _encodeKeyId(encoder, dictionary);
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&keyid);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(EncodeAlg, _encodeKeyName)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x0E, 0x00, 40,
+ // --- name
+ 0x00, 0x00, 0x00, 16,
+ 0x00, 0x03, 0x00, 5,
+ 'a', 'p', 'p', 'l',
+ 'e',
+ 0x00, 0x03, 0x00, 3,
+ 'p', 'i', 'e',
+ // --- keyid
+ 0x00, 0x01, 0x00, 4,
+ 0xa1, 0xa2, 0xa3, 0xa4,
+ // --- hash
+ 0x00, 0x02, 0x00, 8,
+ 0xb1, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8,
+ };
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ PARCBuffer *keyid = parcBuffer_Wrap(encoded, sizeof(encoded), 28, 32);
+ PARCBuffer *hash = parcBuffer_Wrap(encoded, sizeof(encoded), 36, 44);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxName *name = ccnxName_CreateFromCString("lci:/3=apple/3=pie");
+ CCNxLink *link = ccnxLink_Create(name, keyid, hash);
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxValidationFacadeV1_SetKeyName(dictionary, link);
+
+ ssize_t length = _encodeKeyName(encoder, dictionary);
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&keyid);
+ parcBuffer_Release(&hash);
+ ccnxName_Release(&name);
+ ccnxLink_Release(&link);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(EncodeAlg, _encodeSignatureTime_Specified)
+{
+ uint64_t sigtime = 0x1122334455667788ULL;
+ uint8_t encoded[] = {
+ 0x00, 0x0F, 0x00, 8,
+ 0x11, 0x22, 0x33, 0x44,
+ 0x55, 0x66, 0x77, 0x88
+ };
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxValidationFacadeV1_SetSigningTime(dictionary, sigtime);
+
+ ssize_t length = _encodeSignatureTime(encoder, dictionary);
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+/*
+ * Do not specify a signing time, but rather set a Signer and let the code
+ * create the time on its own
+ */
+LONGBOW_TEST_CASE(EncodeAlg, _encodeSignatureTime_Generated)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ PARCBuffer *password = parcBuffer_Wrap("password", 8, 0, 8);
+ PARCSigner *signer = ccnxValidationHmacSha256_CreateSigner(password);
+ ccnxCodecTlvEncoder_SetSigner(encoder, signer);
+ parcSigner_Release(&signer);
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+
+ ssize_t length = _encodeSignatureTime(encoder, dictionary);
+ assertTrue(length == 12, "Wrong length, expected 12, got %zd", length);
+
+ parcBuffer_Release(&password);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(EncodePayload)
+{
+ LONGBOW_RUN_TEST_CASE(EncodePayload, payload_Specified);
+ LONGBOW_RUN_TEST_CASE(EncodePayload, payload_Generated);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(EncodePayload)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(EncodePayload)
+{
+ 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(EncodePayload, payload_Specified)
+{
+ uint8_t encoded[] = {
+ 0x11, 0x22, 0x33, 0x44,
+ 0x55, 0x66, 0x77, 0x88
+ };
+
+ PARCBuffer *truth = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ccnxValidationFacadeV1_SetPayload(dictionary, truth);
+
+ ssize_t length = ccnxCodecSchemaV1ValidationEncoder_EncodePayload(encoder, dictionary);
+ assertTrue(length == sizeof(encoded), "Wrong length, expected %zu got %zd", sizeof(encoded), length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ parcBuffer_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+/*
+ * Put the guts of v1_interest_nameA_crc32c in to the encoding buffer and mark it
+ * as the signature block. Generate the CRC and make sure we got the right thing.
+ */
+LONGBOW_TEST_CASE(EncodePayload, payload_Generated)
+{
+ TlvExtent interestExtent = getTruthTableExtent(TRUTHTABLENAME(v1_interest_nameA_crc32c), V1_MANIFEST_INT_INTEREST);
+
+ // This will test against the string (Interest, ValidationAlg, ValidationPayload)
+ PARCBuffer *truth = parcBuffer_Wrap(v1_interest_nameA_crc32c,
+ sizeof(v1_interest_nameA_crc32c),
+ interestExtent.offset,
+ sizeof(v1_interest_nameA_crc32c));
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ PARCSigner *signer = ccnxValidationCRC32C_CreateSigner();
+ ccnxCodecTlvEncoder_SetSigner(encoder, signer);
+ parcSigner_Release(&signer);
+
+ // This will append from the beginning of the Interest message up to the end of the ValidationAlg
+ // This space is all marked as the "to-be-signed" section.
+ ccnxCodecTlvEncoder_MarkSignatureStart(encoder);
+ size_t signedInfoLenth = sizeof(v1_interest_nameA_crc32c) - 8 - interestExtent.offset;
+ ccnxCodecTlvEncoder_AppendRawArray(encoder, signedInfoLenth, v1_interest_nameA_crc32c + interestExtent.offset);
+ ccnxCodecTlvEncoder_MarkSignatureEnd(encoder);
+
+ // add the validation payload container, then generate the signature
+ ccnxCodecTlvEncoder_AppendContainer(encoder, CCNxCodecSchemaV1Types_MessageType_ValidationPayload, 4);
+
+ // Do the actual encoding. This will calculate the signature on the fly.
+ CCNxTlvDictionary *dictionary = ccnxCodecSchemaV1TlvDictionary_CreateContentObject();
+ ssize_t length = ccnxCodecSchemaV1ValidationEncoder_EncodePayload(encoder, dictionary);
+ assertTrue(length == 4, "Wrong length, expected 4 got %zd", length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ // Tests that we got the right signature (CRC32c in this case)
+ assertTrue(parcBuffer_Equals(truth, test), "Wrong buffer")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+}
+
+// =========================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodecSchemaV1_ValidationDecoder);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/testrig_encoder.c b/libccnx-common/ccnx/common/codec/schema_v1/test/testrig_encoder.c
new file mode 100644
index 00000000..f925dd28
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/testrig_encoder.c
@@ -0,0 +1,472 @@
+/*
+ * 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/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+#include <ccnx/common/codec/ccnxCodec_EncodingBuffer.h>
+
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h>
+
+
+#include <ccnx/common/codec/schema_v1/testdata/v1_testrig_truthTable.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_PacketEncoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h>
+
+#include <ccnx/common/codec/test/testrig_Compare.c>
+
+/**
+ * Finds a row in the truthtable where bodyManifest is TRUE and the
+ * indexOrKey equals 'key'.
+ */
+TlvExtent
+getTruthTableExtent(TruthTableEntry *ttentry, int key)
+{
+ for (int i = 0; ttentry[i].indexOrKey != T_INVALID; i++) {
+ if (ttentry[i].bodyManifest && ttentry[i].indexOrKey == key) {
+ return ttentry[i].extent;
+ }
+ }
+ return (TlvExtent) { 0, 0 };
+}
+
+/**
+ * Finds a row in the truthtable where bodyManifest is FALSE and the
+ * indexOrKey equals 'key'.
+ */
+TlvExtent
+getTruthTableHeaderExtent(TruthTableEntry *ttentry, int key)
+{
+ for (int i = 0; ttentry[i].indexOrKey != T_INVALID; i++) {
+ if (!ttentry[i].bodyManifest && ttentry[i].indexOrKey == key) {
+ return ttentry[i].extent;
+ }
+ }
+ return (TlvExtent) { 0, 0 };
+}
+
+typedef struct test_data {
+ // the memory region extracted from a Truth Table entry
+ PARCBuffer *memoryRegion;
+
+ CCNxCodecTlvEncoder *encoder;
+ CCNxTlvDictionary *dictionary;
+
+ uint8_t *packet;
+ size_t packetLength;
+ TruthTableEntry *truthTable;
+
+ // If the user creates one of these, we'll destroy it.
+ PARCSigner *signer;
+} TestData;
+
+static SchemaV1ManifestContentObjectBody manifestContentObjectContainerArray[] = {
+ V1_MANIFEST_OBJ_CONTENTOBJECT,
+ V1_MANIFEST_OBJ_NAMEAUTH,
+ V1_MANIFEST_OBJ_ValidationPayload,
+ V1_MANIFEST_OBJ_KEYNAME,
+ V1_MANIFEST_OBJ_METADATA,
+ V1_MANIFEST_OBJ_ValidationAlg,
+ V1_MANIFEST_OBJ_BODYEND
+};
+
+static bool
+isContentObjectContainer(SchemaV1ManifestContentObjectBody value)
+{
+ for (int i = 0; manifestContentObjectContainerArray[i] != V1_MANIFEST_OBJ_BODYEND; i++) {
+ if (value == manifestContentObjectContainerArray[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * The testdata truth tables were written with the tlv_1.0 array indicies, so we
+ * need to translate those old indicies to the new indicies.
+ */
+static CCNxCodecSchemaV1TlvDictionary_MessageFastArray
+translateTestDataManifestToSchemaKey(SchemaV1ManifestContentObjectBody oldKey)
+{
+ switch (oldKey) {
+ case V1_MANIFEST_INT_NAME:
+ // fallthrough
+ case V1_MANIFEST_OBJ_NAME:
+ return CCNxCodecSchemaV1TlvDictionary_MessageFastArray_NAME;
+
+ case V1_MANIFEST_OBJ_PAYLOAD:
+ return CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOAD;
+
+ case V1_MANIFEST_OBJ_KEYID:
+ return (CCNxCodecSchemaV1TlvDictionary_MessageFastArray) CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYID;
+
+ case V1_MANIFEST_OBJ_CRYPTO_SUITE:
+ return (CCNxCodecSchemaV1TlvDictionary_MessageFastArray) CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CRYPTO_SUITE;
+
+ case V1_MANIFEST_OBJ_KEY:
+ return (CCNxCodecSchemaV1TlvDictionary_MessageFastArray) CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEY;
+
+ case V1_MANIFEST_OBJ_CERT:
+ return (CCNxCodecSchemaV1TlvDictionary_MessageFastArray) CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_CERT;
+
+ case V1_MANIFEST_OBJ_KEYNAME_NAME:
+ return (CCNxCodecSchemaV1TlvDictionary_MessageFastArray) CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_NAME;
+
+ case V1_MANIFEST_OBJ_KEYNAME_OBJHASH:
+ return (CCNxCodecSchemaV1TlvDictionary_MessageFastArray) CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_KEYNAME_OBJHASH;
+
+ case V1_MANIFEST_OBJ_OBJ_TYPE:
+ return CCNxCodecSchemaV1TlvDictionary_MessageFastArray_PAYLOADTYPE;
+
+ case V1_MANIFEST_OBJ_SIGBITS:
+ return (CCNxCodecSchemaV1TlvDictionary_MessageFastArray) CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_PAYLOAD;
+
+ case V1_MANIFEST_OBJ_SigningTime:
+ return (CCNxCodecSchemaV1TlvDictionary_MessageFastArray) CCNxCodecSchemaV1TlvDictionary_ValidationFastArray_SIGNTIME;
+
+ case V1_MANIFEST_OBJ_ENDSEGMENT:
+ return CCNxCodecSchemaV1TlvDictionary_MessageFastArray_ENDSEGMENT;
+
+ case V1_MANIFEST_INT_KEYID:
+ return CCNxCodecSchemaV1TlvDictionary_MessageFastArray_KEYID_RESTRICTION;
+
+ case V1_MANIFEST_INT_OBJHASH:
+ return CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION;
+
+ default:
+ trapIllegalValue(oldKey, "Unexpected old manifest value: %d", oldKey);
+ break;
+ }
+ return -1;
+}
+
+/**
+ * The testdata truth tables were written with the tlv_1.0 array indicies, so we
+ * need to translate those old indicies to the new indicies.
+ */
+static CCNxCodecSchemaV1TlvDictionary_HeadersFastArray
+translateOldOptionalHeadersManifestToNewKey(CCNxTlvDictionary *packetDictionary, int oldKey)
+{
+ if (ccnxTlvDictionary_IsInterest(packetDictionary)) {
+ switch (oldKey) {
+ case V1_MANIFEST_INT_LIFETIME:
+ return CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_InterestLifetime;
+
+ case V1_MANIFEST_INT_E2EFRAG:
+ return CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_INTFRAG;
+
+ default:
+ trapIllegalValue(oldKey, "Unexpected old manifest value: %d", oldKey);
+ break;
+ }
+ } else if (ccnxTlvDictionary_IsContentObject(packetDictionary)) {
+ switch (oldKey) {
+ case V1_MANIFEST_OBJ_E2EFRAG:
+ return CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_OBJFRAG;
+
+ default:
+ trapIllegalValue(oldKey, "Unexpected old manifest value: %d", oldKey);
+ break;
+ }
+ }
+ return -1;
+}
+
+static void
+addBuffer(TestData *data, CCNxTlvDictionary *packetDictionary, size_t item_start, size_t item_end, uint32_t translatedKey)
+{
+ PARCBuffer *itemBuffer = parcBuffer_Wrap(data->packet, data->packetLength, item_start, item_end);
+ ccnxTlvDictionary_PutBuffer(packetDictionary, translatedKey, itemBuffer);
+ parcBuffer_Release(&itemBuffer);
+}
+
+/**
+ * The extent should be treated like a CCNxName, so decode it and add it as a CCNxName.
+ */
+static void
+addName(TestData *data, CCNxTlvDictionary *packetDictionary, size_t item_start, size_t item_end, uint32_t translatedKey)
+{
+ // we need to backup 4 bytes to the the TLV container
+ PARCBuffer *itemBuffer = parcBuffer_Wrap(data->packet, data->packetLength, item_start - 4, item_end);
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(itemBuffer);
+ CCNxName *name = ccnxCodecSchemaV1NameCodec_Decode(decoder, CCNxCodecSchemaV1Types_CCNxMessage_Name);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+
+ ccnxTlvDictionary_PutName(packetDictionary, translatedKey, name);
+ ccnxName_Release(&name);
+ parcBuffer_Release(&itemBuffer);
+}
+
+
+/**
+ * Called on the body of a content object, does not include the fixed header or optional headers
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return <#value#> <#explanation#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static void
+buildContentObjectDictionary(TestData *data, CCNxTlvDictionary *packetDictionary, TlvExtent extent)
+{
+ size_t start = extent.offset;
+ size_t end = start + extent.length;
+
+ ccnxTlvDictionary_SetMessageType_ContentObject(packetDictionary, CCNxTlvDictionary_SchemaVersion_V1);
+
+ for (int i = 0; data->truthTable[i].indexOrKey != T_INVALID; i++) {
+ size_t item_start = data->truthTable[i].extent.offset;
+ size_t item_end = item_start + data->truthTable[i].extent.length;
+
+ // Is this item included in the given extent?
+ if (start < item_start && item_end <= end) {
+ // Is it a container or a nested dictionary? This check only applies to a ContentObject
+ if (!isContentObjectContainer(data->truthTable[i].indexOrKey)) {
+ uint32_t translatedKey = translateTestDataManifestToSchemaKey(data->truthTable[i].indexOrKey);
+
+ if (data->truthTable[i].indexOrKey == V1_MANIFEST_OBJ_NAME) {
+ addName(data, packetDictionary, item_start, item_end, translatedKey);
+ } else {
+ addBuffer(data, packetDictionary, item_start, item_end, translatedKey);
+ }
+ }
+ }
+ }
+}
+
+static void
+buildInterestDictionary(TestData *data, CCNxTlvDictionary *packetDictionary, TlvExtent extent)
+{
+ size_t start = extent.offset;
+ size_t end = start + extent.length;
+
+ ccnxTlvDictionary_SetMessageType_Interest(packetDictionary, CCNxTlvDictionary_SchemaVersion_V1);
+
+ for (int i = 0; data->truthTable[i].indexOrKey != T_INVALID && data->truthTable[i].bodyManifest; i++) {
+ size_t item_start = data->truthTable[i].extent.offset;
+ size_t item_end = item_start + data->truthTable[i].extent.length;
+
+ // Is this item included in the given extent?
+ if (start < item_start && item_end <= end) {
+ uint32_t translatedKey = translateTestDataManifestToSchemaKey(data->truthTable[i].indexOrKey);
+
+ if (data->truthTable[i].indexOrKey == V1_MANIFEST_INT_NAME) {
+ addName(data, packetDictionary, item_start, item_end, translatedKey);
+ } else {
+ addBuffer(data, packetDictionary, item_start, item_end, translatedKey);
+ }
+ }
+ }
+}
+
+/**
+ * Make a dictionary entry for everything inside the selected extent, not including it
+ *
+ * Use the truth table and for each listed item whose extent is within the given extent,
+ * add a dictionary entry
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return <#value#> <#explanation#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static void
+buildMessageDictionary(TestData *data, CCNxTlvDictionary *dictionary, TlvExtent extent)
+{
+ uint8_t packetType = data->packet[1];
+ switch (packetType) {
+ case CCNxCodecSchemaV1Types_PacketType_Interest:
+ buildInterestDictionary(data, dictionary, extent);
+ break;
+
+ case CCNxCodecSchemaV1Types_PacketType_ContentObject:
+ buildContentObjectDictionary(data, dictionary, extent);
+ break;
+
+ case CCNxCodecSchemaV1Types_PacketType_InterestReturn:
+ trapNotImplemented("not implemented");
+ break;
+
+ default:
+ trapIllegalValue(packetType, "Unknown PacketType");
+ }
+}
+
+static void
+buildSetDictionaryType(TestData *data, CCNxTlvDictionary *dictionary)
+{
+ uint8_t packetType = data->packet[1];
+ switch (packetType) {
+ case CCNxCodecSchemaV1Types_PacketType_Interest:
+ ccnxTlvDictionary_SetMessageType_Interest(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ break;
+
+ case CCNxCodecSchemaV1Types_PacketType_ContentObject:
+ ccnxTlvDictionary_SetMessageType_ContentObject(dictionary, CCNxTlvDictionary_SchemaVersion_V1);
+ break;
+
+ case CCNxCodecSchemaV1Types_PacketType_InterestReturn:
+ trapNotImplemented("not implemented");
+ break;
+
+ default:
+ trapIllegalValue(packetType, "Unknown PacketType");
+ }
+}
+
+/**
+ * Builds a packet dictionary with OptionalHeaders and Message
+ *
+ * <#Paragraphs Of Explanation#>
+ *
+ * @param [<#in out in,out#>] <#name#> <#description#>
+ *
+ * @return <#value#> <#explanation#>
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+static void
+buildPacketDictionary(TestData *data, CCNxTlvDictionary *packetDictionary, TlvExtent extent)
+{
+ buildSetDictionaryType(data, packetDictionary);
+
+ size_t start = extent.offset;
+ size_t end = start + extent.length;
+
+ for (int i = 0; data->truthTable[i].indexOrKey != T_INVALID; i++) {
+ size_t item_start = data->truthTable[i].extent.offset;
+ size_t item_end = item_start + data->truthTable[i].extent.length;
+
+ // Is this item included in the given extent?
+ if (start < item_start && item_end <= end) {
+ if (data->truthTable[i].bodyManifest == false) {
+ PARCBuffer *itemBuffer = parcBuffer_Wrap(data->packet, data->packetLength, item_start, item_end);
+ uint32_t translatedKey = translateOldOptionalHeadersManifestToNewKey(packetDictionary, data->truthTable[i].indexOrKey);
+ ccnxTlvDictionary_PutBuffer(packetDictionary, translatedKey, itemBuffer);
+ parcBuffer_Release(&itemBuffer);
+ } else {
+ buildMessageDictionary(data, packetDictionary, data->truthTable[i].extent);
+ }
+
+ // advance start to skip over whatever we just included
+ start = item_end;
+ }
+ }
+}
+
+/**
+ * Wraps the given (packet, length) in a PARCBuffer where the data->memoryRegion member will be set
+ * to a given extent within that PARCBuffer. The function will locate the truthTableKey in the truthTable and
+ * use it's extent as the bounds for the wrapped packet.
+ *
+ * For example, if the key V1_INT_NAME has the extent {32, 12}, then the PARCBuffer will wrap the packet
+ * memory and it will have and offset of 32 and a limit of 12.
+ */
+TestData *
+commonSetup(uint8_t *packet, size_t length, TruthTableEntry *truthTable, int truthTableKey)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ TlvExtent extent = getTruthTableExtent(truthTable, truthTableKey);
+
+ data->memoryRegion = parcBuffer_Wrap(packet, length, extent.offset, extent.offset + extent.length);
+ data->encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(data->encoder);
+
+ // use the content object lenghts, they are the largest
+ data->dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+
+ data->packet = packet;
+ data->packetLength = length;
+ data->truthTable = truthTable;
+
+ buildMessageDictionary(data, data->dictionary, extent);
+ return data;
+}
+
+/**
+ * Wraps a packet like commonSetup, but will do the whole packet including headers not just
+ * the message body. This is used by the PacketEncoder tests.
+ */
+TestData *
+testrigencoder_CommonSetupWholePacket(uint8_t *packet, size_t length, TruthTableEntry *truthTable)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->memoryRegion = parcBuffer_Wrap(packet, length, 0, length);
+ data->encoder = ccnxCodecTlvEncoder_Create();
+
+ // use the content object lenghts, they are the largest
+ data->dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+
+ data->packet = packet;
+ data->packetLength = length;
+ data->truthTable = truthTable;
+
+ buildPacketDictionary(data, data->dictionary, (TlvExtent) { 0, length });
+
+ return data;
+}
+
+void
+testrigencoder_CommonTeardown(TestData *data)
+{
+ ccnxTlvDictionary_Release(&data->dictionary);
+ ccnxCodecTlvEncoder_Destroy(&data->encoder);
+ parcBuffer_Release(&data->memoryRegion);
+
+ if (data->signer) {
+ parcSigner_Release(&data->signer);
+ }
+
+ parcMemory_Deallocate((void **) &data);
+}
+
+void
+testDisplayIoVec(CCNxCodecEncodingBufferIOVec *vec)
+{
+ printf("Display iovec %p with %d elements\n", (void *) vec, vec->iovcnt);
+ size_t totalLength = 0;
+ for (int i = 0; i < vec->iovcnt; i++) {
+ totalLength += vec->iov[i].iov_len;
+ printf(" %3d: base %p length %4zu total length %4zu\n", i, (void *) vec->iov[i].iov_base, vec->iov[i].iov_len, totalLength);
+ }
+ printf("done\n\n");
+}
+
+void
+testExecute(TestData *data, ssize_t (*encoderFunction)(CCNxCodecTlvEncoder *encoder, CCNxTlvDictionary *dictionary))
+{
+ encoderFunction(data->encoder, data->dictionary);
+ testCompareEncoderToBuffer(data->encoder, data->memoryRegion);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/test/testrig_packetwrapper.c b/libccnx-common/ccnx/common/codec/schema_v1/test/testrig_packetwrapper.c
new file mode 100644
index 00000000..9a213b13
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/test/testrig_packetwrapper.c
@@ -0,0 +1,516 @@
+/*
+ * 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.
+ */
+
+/**
+ * This test rig sets up test data to wrap a packet and prepare it for use in a decoder
+ *
+ * A hand-encoded packet, such as from the testdata directory can be passed to commonSetup and then
+ * run automated tests against it based on its manifest.
+ *
+ * Example:
+ * @code
+ *
+ * static uint8_t object_nameC_keyid3_protoinfo[] = {
+ * 0x00, 0x02, 0x00, 110, // ver = 0, type = object, length = 110
+ * 0x00, 0x00, 0x00, 5, // reserved = 0, header length = 5
+ * // ---------------------------
+ * // snip middle of packet
+ * // ------------------------
+ * // byte offset 76
+ * 0x00, 0x03, 0x00, 26, // Protocol Information, length = 26
+ * 0x00, 0x0B, 0x00, 17, // Object Metadata, length = 17
+ * 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+ * 0x04, // LINK
+ * 0x00, 0x0D, 0x00, 8, // Creation Time
+ * 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+ * 0x4B, 0x19, 0x84, 0x00,
+ * 0x00, 0x19, 0x00, 0x01, // EndSegment, length = 1
+ * 42,
+ * // ---------------------------
+ * // snip to end of packet
+ * // ---------------------------
+ * };
+ *
+ * static TruthTableEntry TRUTHTABLENAME(object_nameC_keyid3_protoinfo)[] = {
+ * { .wellKnownType = true, .indexOrKey = MANIFEST_OBJ_METADATA, .bodyManifest=true, .extent = { 80, 17} },
+ * { .wellKnownType = true, .indexOrKey = MANIFEST_OBJ_OBJ_TYPE, .bodyManifest=true, .extent = { 84, 1} },
+ * { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0} },
+ * };
+ *
+ * LONGBOW_TEST_FIXTURE_SETUP(Global)
+ * {
+ * commonSetup(testCase, object_nameC_keyid3_protoinfo, sizeof(object_nameC_keyid3_protoinfo), object_nameC_keyid3_protoinfo_truthTableEntries, MANIFEST_OBJ_METADATA);
+ * return LONGBOW_STATUS_SUCCEEDED;
+ * }
+ *
+ * LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV0ProtoInfo_GetEndSegmentNumber)
+ * {
+ * testInt32Getter(testCase, MANIFEST_OBJ_OBJ_TYPE, ccnxCodecSchemaV0Metadata_Decode, ccnxCodecSchemaV0Metadata_GetContentType);
+ * }
+ *
+ * @endcode
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <ccnx/common/codec/ccnxCodec_TlvUtilities.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_NameCodec.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_HashCodec.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_testrig_truthTable.h>
+
+/**
+ * Finds a row in the truthtable where bodyManifest is TRUE and the
+ * indexOrKey equals 'key'.
+ */
+TlvExtent
+getTruthTableExtent(TruthTableEntry *ttentry, int key)
+{
+ for (int i = 0; ttentry[i].indexOrKey != T_INVALID; i++) {
+ if (ttentry[i].bodyManifest && ttentry[i].indexOrKey == key) {
+ return ttentry[i].extent;
+ }
+ }
+ return (TlvExtent) { 0, 0 };
+}
+
+/**
+ * Finds a row in the truthtable where bodyManifest is FALSE and the
+ * indexOrKey equals 'key'.
+ */
+TlvExtent
+getTruthTableHeaderExtent(TruthTableEntry *ttentry, int key)
+{
+ for (int i = 0; ttentry[i].indexOrKey != T_INVALID; i++) {
+ if (!ttentry[i].bodyManifest && ttentry[i].indexOrKey == key) {
+ return ttentry[i].extent;
+ }
+ }
+ return (TlvExtent) { 0, 0 };
+}
+
+typedef struct test_data {
+ PARCBuffer *interest;
+ CCNxCodecTlvDecoder *decoder;
+ CCNxTlvDictionary *dictionary;
+
+ uint8_t *packet;
+ size_t packetLength;
+ TruthTableEntry *truthTable;
+} TestData;
+
+/**
+ * Wraps the given (packet, length) in a PARCBuffer where the data->memoryRegion member will be set
+ * to a given extent within that PARCBuffer. The function will locate the truthTableKey in the truthTable and
+ * use it's extent as the bounds for the wrapped packet.
+ *
+ * For example, if the key V1_INT_NAME has the extent {32, 12}, then the PARCBuffer will wrap the packet
+ * memory and it will have and offset of 32, position 0, and a limit of 12.
+ */
+TestData *
+commonSetup(uint8_t *packet, size_t length, TruthTableEntry *truthTable, int truthTableKey)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ TlvExtent extent = getTruthTableExtent(truthTable, truthTableKey);
+
+ data->interest = parcBuffer_Wrap(packet, length, extent.offset, extent.offset + extent.length);
+ data->decoder = ccnxCodecTlvDecoder_Create(data->interest);
+
+ // content objects have more fields than interests, so use that
+ data->dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+
+ data->packet = packet;
+ data->packetLength = length;
+ data->truthTable = truthTable;
+ return data;
+}
+
+void
+commonSetupWholePacket(LongBowTestCase *testCase, uint8_t *packet, size_t length, TruthTableEntry *truthTable)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->interest = parcBuffer_Wrap(packet, length, 0, length);
+ data->decoder = ccnxCodecTlvDecoder_Create(data->interest);
+ data->dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+
+ data->packet = packet;
+ data->packetLength = length;
+ data->truthTable = truthTable;
+
+ longBowTestCase_SetClipBoardData(testCase, data);
+}
+
+void
+commonTeardown(TestData *data)
+{
+ ccnxTlvDictionary_Release(&data->dictionary);
+ ccnxCodecTlvDecoder_Destroy(&data->decoder);
+ parcBuffer_Release(&data->interest);
+ parcMemory_Deallocate((void **) &data);
+}
+
+/**
+ * Tests that an int32_t getter returns the right value
+ *
+ * Given a packet byte array and a truth table (see transport/test_tools/testdata/testrig_truthTable.h),
+ * check that the buffer the decoder parsed is the right buffer.
+ *
+ * The function will run the specified decoder on the TestData's packet and put the results in the
+ * TestData's dictionary. It will then call the specified getter and make sure its value is equal
+ * to the truth table's value.
+ *
+ * The function will assert if the test fails.
+ *
+ * @param [in] testCase Used to get the clipboard data with the TestData member
+ * @param [in] truthTableKey Used to match the .indexOrKey truth table member
+ * @param [in] containerDecoder The decoder to use on the packet contained in TestData
+ * @param [in] getter The function to call to fetch a decoded value
+ *
+ * Example:
+ * @code
+ *
+ * static uint8_t object_nameC_keyid3_protoinfo[] = {
+ * 0x00, 0x02, 0x00, 110, // ver = 0, type = object, length = 110
+ * 0x00, 0x00, 0x00, 5, // reserved = 0, header length = 5
+ * // ---------------------------
+ * // snip middle of packet
+ * // ------------------------
+ * // byte offset 76
+ * 0x00, 0x03, 0x00, 26, // Protocol Information, length = 26
+ * 0x00, 0x0B, 0x00, 17, // Object Metadata, length = 17
+ * 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+ * 0x04, // LINK
+ * 0x00, 0x0D, 0x00, 8, // Creation Time
+ * 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+ * 0x4B, 0x19, 0x84, 0x00,
+ * 0x00, 0x19, 0x00, 0x01, // EndSegment, length = 1
+ * 42,
+ * // ---------------------------
+ * // snip to end of packet
+ * // ---------------------------
+ * };
+ *
+ * static TruthTableEntry TRUTHTABLENAME(object_nameC_keyid3_protoinfo)[] = {
+ * { .wellKnownType = true, .indexOrKey = MANIFEST_OBJ_METADATA, .bodyManifest=true, .extent = { 80, 17} },
+ * { .wellKnownType = true, .indexOrKey = MANIFEST_OBJ_OBJ_TYPE, .bodyManifest=true, .extent = { 84, 1} },
+ * { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0} },
+ * };
+ *
+ * LONGBOW_TEST_FIXTURE_SETUP(Global)
+ * {
+ * commonSetup(testCase, object_nameC_keyid3_protoinfo, sizeof(object_nameC_keyid3_protoinfo), object_nameC_keyid3_protoinfo_truthTableEntries, MANIFEST_OBJ_METADATA);
+ * return LONGBOW_STATUS_SUCCEEDED;
+ * }
+ *
+ * LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV0ProtoInfo_GetEndSegmentNumber)
+ * {
+ * testInt32Getter(testCase, MANIFEST_OBJ_OBJ_TYPE, ccnxCodecSchemaV0Metadata_Decode, ccnxCodecSchemaV0Metadata_GetContentType);
+ * }
+ * * @endcode
+ */
+void
+testInt32Getter(LongBowTestCase *testCase, int truthTableKey, bool containerDecoder(CCNxCodecTlvDecoder *, CCNxTlvDictionary *),
+ int32_t (*getter)(CCNxTlvDictionary *))
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ containerDecoder(data->decoder, data->dictionary);
+ int32_t testvalue = getter(data->dictionary);
+
+ // look up the true name buffer from the truth table
+ TlvExtent extent = getTruthTableExtent(data->truthTable, truthTableKey);
+ PARCBuffer *truthbuffer = parcBuffer_Wrap(data->packet, data->packetLength, extent.offset, extent.offset + extent.length);
+ uint64_t truthvalue = -2;
+ ccnxCodecTlvUtilities_GetVarInt(truthbuffer, parcBuffer_Remaining(truthbuffer), &truthvalue);
+
+ parcBuffer_Release(&truthbuffer);
+
+ assertTrue(testvalue == (int32_t) truthvalue, "Wrong value, got %d expected %d", testvalue, (int32_t) truthvalue);
+}
+
+/**
+ * Tests that an int64_t getter returns the right value
+ *
+ * Given a packet byte array and a truth table (see transport/test_tools/testdata/testrig_truthTable.h),
+ * check that the buffer the decoder parsed is the right buffer.
+ *
+ * The function will run the specified decoder on the TestData's packet and put the results in the
+ * TestData's dictionary. It will then call the specified getter and make sure its value is equal
+ * to the truth table's value.
+ *
+ * The function will assert if the test fails.
+ *
+ * @param [in] testCase Used to get the clipboard data with the TestData member
+ * @param [in] truthTableKey Used to match the .indexOrKey truth table member
+ * @param [in] containerDecoder The decoder to use on the packet contained in TestData
+ * @param [in] getter The function to call to fetch a decoded value
+ *
+ * Example:
+ * @code
+ *
+ * static uint8_t object_nameC_keyid3_protoinfo[] = {
+ * 0x00, 0x02, 0x00, 110, // ver = 0, type = object, length = 110
+ * 0x00, 0x00, 0x00, 5, // reserved = 0, header length = 5
+ * // ---------------------------
+ * // snip middle of packet
+ * // ------------------------
+ * // byte offset 76
+ * 0x00, 0x03, 0x00, 26, // Protocol Information, length = 26
+ * 0x00, 0x0B, 0x00, 17, // Object Metadata, length = 17
+ * 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+ * 0x04, // LINK
+ * 0x00, 0x0D, 0x00, 8, // Creation Time
+ * 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+ * 0x4B, 0x19, 0x84, 0x00,
+ * 0x00, 0x19, 0x00, 0x01, // EndSegment, length = 1
+ * 42,
+ * // ---------------------------
+ * // snip to end of packet
+ * // ---------------------------
+ * };
+ *
+ * static TruthTableEntry TRUTHTABLENAME(object_nameC_keyid3_protoinfo)[] = {
+ * { .wellKnownType = true, .indexOrKey = MANIFEST_OBJ_PROTOINFO, .bodyManifest=true, .extent = { 76, 26} },
+ * { .wellKnownType = true, .indexOrKey = MANIFEST_OBJ_ENDSEGMENT, .bodyManifest=true, .extent = {101, 1} },
+ * { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0} },
+ * };
+ *
+ * LONGBOW_TEST_FIXTURE_SETUP(Global)
+ * {
+ * commonSetup(testCase, object_nameC_keyid3_protoinfo, sizeof(object_nameC_keyid3_protoinfo), object_nameC_keyid3_protoinfo_truthTableEntries, MANIFEST_OBJ_PROTOINFO);
+ * return LONGBOW_STATUS_SUCCEEDED;
+ * }
+ *
+ * LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV0ProtoInfo_GetEndSegmentNumber)
+ * {
+ * testInt64Getter(testCase, MANIFEST_OBJ_ENDSEGMENT, ccnxCodecSchemaV0ProtoInfo_Decode, ccnxCodecSchemaV0ProtoInfo_GetEndSegmentNumber);
+ * }
+ *
+ * @endcode
+ */
+void
+testInt64Getter(TestData *data, int truthTableKey, bool containerDecoder(CCNxCodecTlvDecoder *, CCNxTlvDictionary *),
+ int64_t (*getter)(CCNxTlvDictionary *))
+{
+ containerDecoder(data->decoder, data->dictionary);
+ int64_t testvalue = getter(data->dictionary);
+
+ // look up the true name buffer from the truth table
+ TlvExtent extent = getTruthTableExtent(data->truthTable, truthTableKey);
+ PARCBuffer *truthbuffer = parcBuffer_Wrap(data->packet, data->packetLength, extent.offset, extent.offset + extent.length);
+ uint64_t truthvalue = -2;
+ ccnxCodecTlvUtilities_GetVarInt(truthbuffer, parcBuffer_Remaining(truthbuffer), &truthvalue);
+
+ parcBuffer_Release(&truthbuffer);
+
+ assertTrue(testvalue == (int64_t) truthvalue, "Wrong value, got %" PRId64 " expected %" PRId64, testvalue, (int64_t) truthvalue);
+}
+
+/**
+ * Tests that a buffer getter returns the right buffer
+ *
+ * Given a packet byte array and a truth table (see transport/test_tools/testdata/testrig_truthTable.h),
+ * check that the buffer the decoder parsed is the right buffer.
+ *
+ * The function will run the specified decoder on the TestData's packet and put the results in the
+ * TestData's dictionary. It will then call the specified getter and make sure its value is equal
+ * to the truth table's value.
+ *
+ * The function will assert if the test fails.
+ *
+ * @param [in] testCase Used to get the clipboard data with the TestData member
+ * @param [in] truthTableKey Used to match the .indexOrKey truth table member
+ * @param [in] containerDecoder The decoder to use on the packet contained in TestData
+ * @param [in] getter The function to call to fetch a decoded value
+ *
+ * Example:
+ * @code
+ *
+ * static uint8_t object_nameC_keyid3_protoinfo[] = {
+ * 0x00, 0x02, 0x00, 110, // ver = 0, type = object, length = 110
+ * 0x00, 0x00, 0x00, 5, // reserved = 0, header length = 5
+ * // ---------------------------
+ * // snip middle of packet
+ * // ------------------------
+ * // byte offset = 117
+ * 0x00, 0x05, 0x00, 0x06, // signature block, length = 6
+ * 0x00, 0x0E, 0x00, 0x02, // signature bits, length = 2
+ * 0xBE, 0xEF // value = 0xBEEF
+ * };
+ *
+ * static TruthTableEntry TRUTHTABLENAME(object_nameC_keyid3_protoinfo)[] = {
+ * { .wellKnownType = true, .indexOrKey = MANIFEST_OBJ_SIGBLOCK, .bodyManifest=true, .extent = {117, 6} },
+ * { .wellKnownType = true, .indexOrKey = MANIFEST_OBJ_SIGBITS, .bodyManifest=true, .extent = {121, 2} },
+ * { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0} },
+ * };
+ *
+ * LONGBOW_TEST_FIXTURE_SETUP(Global)
+ * {
+ * commonSetup(testCase, object_nameC_keyid3_protoinfo, sizeof(object_nameC_keyid3_protoinfo), object_nameC_keyid3_protoinfo_truthTableEntries, MANIFEST_OBJ_SIGBLOCK);
+ * return LONGBOW_STATUS_SUCCEEDED;
+ * }
+ *
+ * LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV0SigBlock_GetSignatureBits)
+ * {
+ * testBufferGetter(testCase, MANIFEST_OBJ_SIGBITS, ccnxCodecSchemaV0SigBlock_Decode, ccnxCodecSchemaV0SigBlock_GetSignatureBits);
+ * }
+ *
+ * @endcode
+ */
+void
+testBufferGetter(TestData *data, int truthTableKey, bool containerDecoder(CCNxCodecTlvDecoder *, CCNxTlvDictionary *),
+ PARCBuffer *(*getter)(const CCNxTlvDictionary *))
+{
+ containerDecoder(data->decoder, data->dictionary);
+ PARCBuffer *test = getter(data->dictionary);
+
+ // look up the true name buffer from the truth table
+ TlvExtent extent = getTruthTableExtent(data->truthTable, truthTableKey);
+ PARCBuffer *truth = parcBuffer_Wrap(data->packet, data->packetLength, extent.offset, extent.offset + extent.length);
+
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers not equal")
+ {
+ printf("Expected:\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got:\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truth);
+}
+
+void
+testHashGetter(TestData *data, int truthTableKey, bool containerDecoder(CCNxCodecTlvDecoder *, CCNxTlvDictionary *),
+ PARCCryptoHash *(*getter)(CCNxTlvDictionary *))
+{
+ containerDecoder(data->decoder, data->dictionary);
+ PARCCryptoHash *testHash = getter(data->dictionary);
+
+ // look up the true hash buffer from the truth table
+ TlvExtent extent = getTruthTableExtent(data->truthTable, truthTableKey);
+ PARCBuffer *truthBuffer = parcBuffer_Wrap(data->packet, data->packetLength, extent.offset, extent.offset + extent.length);
+
+ // decode the hash value
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(truthBuffer);
+ PARCCryptoHash *truthHash = ccnxCodecSchemaV1HashCodec_DecodeValue(decoder, extent.length);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+
+ // compare the decoded value against the expected value
+ assertTrue(parcCryptoHash_Equals(testHash, truthHash), "Hashes not equal")
+ {
+ printf("Expected:\n");
+ printf(" %s\n", parcBuffer_ToHexString(parcCryptoHash_GetDigest(truthHash)));
+ printf("Got:\n");
+ printf(" %s\n", parcBuffer_ToHexString(parcCryptoHash_GetDigest(testHash)));
+ }
+
+ parcCryptoHash_Release(&truthHash);
+ parcBuffer_Release(&truthBuffer);
+}
+
+void
+testNameGetter(TestData *data, int truthTableKey, bool containerDecoder(CCNxCodecTlvDecoder *, CCNxTlvDictionary *),
+ CCNxName *(*getter)(CCNxTlvDictionary *))
+{
+ containerDecoder(data->decoder, data->dictionary);
+ CCNxName *test = getter(data->dictionary);
+
+ // look up the true name buffer from the truth table
+ TlvExtent extent = getTruthTableExtent(data->truthTable, truthTableKey);
+
+ // we need to backup 4 bytes to get the TLV container
+ PARCBuffer *truthBuffer =
+ parcBuffer_Wrap(data->packet, data->packetLength, extent.offset - 4, extent.offset + extent.length);
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(truthBuffer);
+ CCNxName *truthName = ccnxCodecSchemaV1NameCodec_Decode(decoder, CCNxCodecSchemaV1Types_CCNxMessage_Name);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+
+ assertTrue(ccnxName_Equals(test, truthName), "Names not equal")
+ {
+ printf("Expected:\n");
+ ccnxName_Display(truthName, 3);
+ printf("Got:\n");
+ ccnxName_Display(test, 3);
+ }
+
+ ccnxName_Release(&truthName);
+ parcBuffer_Release(&truthBuffer);
+}
+
+void
+testMissingInt32Getter(LongBowTestCase *testCase, int32_t (*getter)(CCNxTlvDictionary *))
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ int32_t test = getter(data->dictionary);
+
+ assertTrue(test == -1, "Wrong value, got %d expected %d", test, -1);
+}
+
+/**
+ * Tried to retrieve execute the getter on the dictionary and ensures that
+ * the field is missing.
+ */
+void
+testMissingInt64Getter(LongBowTestCase *testCase, int64_t (*getter)(CCNxTlvDictionary *))
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ int64_t test = getter(data->dictionary);
+
+ assertTrue(test == -1, "Wrong value, got %" PRId64 " expected %d", test, -1);
+}
+
+/**
+ * Tried to retrieve execute the getter on the dictionary and ensures that
+ * the field is missing.
+ */
+void
+testMissingNameGetter(LongBowTestCase *testCase, CCNxName *(*getter)(CCNxTlvDictionary *))
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxName *test = getter(data->dictionary);
+
+ assertNull(test, "Should have gotten null for missing field, got %p", (void *) test);
+}
+
+/**
+ * Tried to retrieve execute the getter on the dictionary and ensures that
+ * the field is missing.
+ */
+void
+testMissingBufferGetter(LongBowTestCase *testCase, PARCBuffer *(*getter)(CCNxTlvDictionary *))
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *test = getter(data->dictionary);
+
+ assertNull(test, "Should have gotten null for missing field, got %p", (void *) test);
+}
+
+/**
+ * Tried to retrieve execute the getter on the dictionary and ensures that
+ * the field is missing.
+ */
+void
+testMissingDictionaryGetter(LongBowTestCase *testCase, CCNxTlvDictionary *(*getter)(CCNxTlvDictionary *))
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *test = getter(data->dictionary);
+
+ assertNull(test, "Should have gotten null for missing field, got %p", (void *) test);
+}
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/CMakeLists.txt b/libccnx-common/ccnx/common/codec/schema_v1/testdata/CMakeLists.txt
new file mode 100644
index 00000000..c5c70ce4
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Enable gcov output for the tests
+add_definitions(--coverage)
+set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
+
+set(TestsExpectedToPass
+ test_ccnxCodecSchemaV1_CryptoSuite
+ test_ccnxCodecSchemaV1_FixedHeaderDecoder
+ test_ccnxCodecSchemaV1_FixedHeaderEncoder
+ test_ccnxCodecSchemaV1_LinkCodec
+ test_ccnxCodecSchemaV1_MessageDecoder
+ test_ccnxCodecSchemaV1_MessageEncoder
+ test_ccnxCodecSchemaV1_NameCodec
+ test_ccnxCodecSchemaV1_NameSegmentCodec
+ test_ccnxCodecSchemaV1_OptionalHeadersDecoder
+ test_ccnxCodecSchemaV1_OptionalHeadersEncoder
+ test_ccnxCodecSchemaV1_PacketDecoder
+ test_ccnxCodecSchemaV1_PacketEncoder
+ test_ccnxCodecSchemaV1_TlvDictionary
+ test_ccnxCodecSchemaV1_ValidationDecoder
+ test_ccnxCodecSchemaV1_ValidationEncoder
+)
+
+
+foreach(test ${TestsExpectedToPass})
+ AddTest(${test})
+endforeach()
+
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_CPISchema.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_CPISchema.h
new file mode 100644
index 00000000..70899d13
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_CPISchema.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.
+ */
+
+/**
+ * Defines the truthtable manifest constants used by the version 1 test vectors.
+ *
+ */
+
+/**
+ * Schema for Control Plane Interface packets. These packets are a TLV wrapping
+ * the control JSON.
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+
+#ifndef Libccnx_v1_CPISchema_h
+#define Libccnx_v1_CPISchema_h
+
+#include <ccnx/common/codec/testdata/tlv_Schema.h>
+
+// -----------------------------------------------------
+// these are the array indicies used to store the TlvExtent for the item
+typedef enum {
+ V1_MANIFEST_CPI_PAYLOAD = 0,
+ V1_MANIFEST_CPI_SIGBITS = 5, // the payload of the signature
+ V1_MANIFEST_CPI_ValidationAlg = 6, // start of validation algorithm
+ V1_MANIFEST_CPI_ValidationPayload = 7, // start of validation payload
+ V1_MANIFEST_CPI_BODYEND = 8
+} V1_ManifestCPIBody;
+
+typedef enum {
+ V1_MANIFEST_CPI_HEADEND = 0
+} V1_ManifestCPIHeaders;
+
+#endif // Libccnx_tlv_CPISchema_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h
new file mode 100644
index 00000000..cb59d937
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+/**
+ * This is from the version 1 codec. All the test vectors in this directory (e.g. interest_nameA.h)
+ * are encoded using these constants. These are no longer used for any functional code, only to interpret the test vectors.
+ *
+ */
+
+#ifndef Libccnx_v1_ContentObjectSchema_h
+#define Libccnx_v1_ContentObjectSchema_h
+
+#include <ccnx/common/codec/testdata/tlv_Schema.h>
+
+#define T_CONTENTOBJECT 0x0002
+
+// these are the array indicies used to store the TlvExtent for the item
+typedef enum {
+ // top level entities
+ V1_MANIFEST_OBJ_NAME = 0,
+ V1_MANIFEST_OBJ_CONTENTOBJECT = 1, // the top container
+ V1_MANIFEST_OBJ_NAMEAUTH = 2,
+ V1_MANIFEST_OBJ_PAYLOADTYPE = 3,
+ V1_MANIFEST_OBJ_PAYLOAD = 4,
+ V1_MANIFEST_OBJ_SIGBITS = 5,
+
+ // inside the name authenticator
+ V1_MANIFEST_OBJ_KEYID = 6,
+ V1_MANIFEST_OBJ_CRYPTO_SUITE = 7,
+ V1_MANIFEST_OBJ_KEY = 8,
+ V1_MANIFEST_OBJ_CERT = 9,
+ V1_MANIFEST_OBJ_KEYNAME = 10,
+ V1_MANIFEST_OBJ_KEYNAME_NAME = 11,
+ V1_MANIFEST_OBJ_KEYNAME_OBJHASH = 12,
+
+ // inside the protocol information
+ V1_MANIFEST_OBJ_METADATA = 13,
+
+ // inside metadata
+ V1_MANIFEST_OBJ_OBJ_TYPE = 14,
+ V1_MANIFEST_OBJ_CREATE_TIME = 15,
+ V1_MANIFEST_OBJ_EXPIRY_TIME = 16,
+
+ // inside signature block
+ V1_MANIFEST_OBJ_ValidationPayload = 17,
+ V1_MANIFEST_OBJ_ENDSEGMENT = 18,
+ V1_MANIFEST_OBJ_PUBKEY = 19,
+
+ V1_MANIFEST_OBJ_ValidationAlg = 20,
+ V1_MANIFEST_OBJ_SigningTime = 21,
+ V1_MANIFEST_OBJ_BODYEND = 22
+} SchemaV1ManifestContentObjectBody;
+
+typedef enum {
+ V1_MANIFEST_OBJ_OPTHEAD = 0,
+ V1_MANIFEST_OBJ_E2EFRAG = 2,
+ V1_MANIFEST_OBJ_FIXEDHEADER = 3,
+ V1_MANIFEST_OBJ_RecommendedCacheTime = 4,
+ V1_MANIFEST_OBJ_HEADEND = 5
+} SchemaV1ManifestContentObjectHeaders;
+
+#endif // Libccnx_tlv_ContentObjectSchema_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h
new file mode 100644
index 00000000..894b3cc7
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h
@@ -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.
+ */
+
+/**
+ * This is from the version 0 codec. All the test vectors in this directory (e.g. interest_nameA.h)
+ * are encoded using these constants. These are no longer used for any functional code, only to interpret the test vectors.
+ *
+ */
+
+#ifndef Libccnx_v1_InterestSchema_h
+#define Libccnx_v1_InterestSchema_h
+
+#include <ccnx/common/codec/testdata/tlv_Schema.h>
+
+// -----------------------------------------------------
+// these are the array indicies used to store the TlvExtent for the item
+typedef enum {
+ V1_MANIFEST_INT_INTEREST = 0, // start of Interest body to end
+
+ V1_MANIFEST_INT_NAME = 1,
+ V1_MANIFEST_INT_KEYID = 2,
+ V1_MANIFEST_INT_OBJHASH = 3,
+ V1_MANIFEST_INT_PAYLOAD = 4,
+ V1_MANIFEST_INT_IPIDM = 5,
+
+ V1_MANIFEST_INT_ValidationAlg = 6, // start of validation algorithm
+ V1_MANIFEST_INT_ValidationPayload = 7, // start of validation payload
+
+ V1_MANIFEST_INT_BODYEND = 7
+} ScheamV1ManifestInterestBody;
+
+typedef enum {
+ V1_MANIFEST_INT_OPTHEAD = 0, // the start of the optional headers
+ V1_MANIFEST_INT_LIFETIME = 1,
+ V1_MANIFEST_INT_E2EFRAG = 2,
+ V1_MANIFEST_INT_HEADEND = 3,
+} ScheamV1ManifestInterestHeaders;
+
+
+#define T_INTEREST 0x0001
+
+#endif // Libccnx_tlv_InterestSchema_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameA_crc32c.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameA_crc32c.h
new file mode 100644
index 00000000..e4695849
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameA_crc32c.h
@@ -0,0 +1,114 @@
+/*
+ * 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 interest_nameA_crc32c.h
+ * @brief Interest with CRC validation
+ *
+ * Ground truth set derived from CRC RevEng http://reveng.sourceforge.net
+ * e.g. reveng -c -m CRC-32C 313233343536373839 gives the canonical check value 0xe306928e
+ *
+ * You can also calcaulate CRC32C online at http://www.zorc.breitbandkatze.de/crc.html using
+ * CRC polynomial 0x1EDC6F41, init 0xFFFFFFFF, final 0xFFFFFFFF, reverse data bytes (check),
+ * and reverse CRC result before final XOR (check).
+ *
+ * you can get the packet dump from the "write_packets" command. here's the detailed steps.
+ * The -c size of 4 in steps 4 and 7 are chosen to make it easy to delete the right number of lines.
+ * there's nothing magic about the "4".
+ *
+ * 1) execute ./write_packets
+ * 2) xxd -r -c 8 v1_content_nameA_crc32c.txt > y
+ * 3) vim -b y
+ * 4) :%!xxd -p -c 4
+ * 5) Delete the frist 44 bytes (11 lines). The first line should now be:
+ * 00020015
+ * 6) Delete the last 8 bytes
+ * The last line two lines should be:
+ * 04000200
+ * 00
+ * What's left is the part to be signed.
+ * 7) :%!xxd -r -p -c 4
+ * 8) :wq
+ * 9) dump the file to one long URL-escaped hex string with
+ * xxd -p -c 256 y | sed 's/[0-9a-f]\{2\}/%&/g'
+ * 10) Copy the hex string to the website and use the settings specified above (don't use 0x in front
+ * of any hex strings). Click "compute!"
+ * 11) The answer should be 2C3CC0Af
+ * 12) Put the byte array from (11) in the Validation Payload.
+ *
+ */
+
+#ifndef v1_content_nameA_crc32c_h
+#define v1_content_nameA_crc32c_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h>
+
+/**
+ * A well formed interest with only a name
+ */
+
+__attribute__((unused))
+static uint8_t v1_content_nameA_crc32c[] = {
+ 0x01, 0x01, 0x00, 85, // ver = 1, type = content object, length = 85
+ 0x00, 0x00, 0x00, 44, // HopLimit = 31, reserved = 0, header length = 44
+ // ------------------------
+ 0x00, 0x04, 0x00, 20, // ContentObject Fragment, length = 20
+ 0x12, 0x23, 0x34, 0x45,
+ 0x56, 0x67, 0x78, 0x89, // fragid 0x1223344556677889
+ 0x05, 0xDC, 0x01, 0x00, // MTU 1500, fragcnt 1, fragnum 0
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, // interest fragment 0x0102030405060708
+ // ------------------------
+ 0x00, 0x02, 0x00, 8, // Recommended Cache Time
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6D, 0xDD, 0x00, // 2 hours (0x6DDD00 milli seconds)
+ // ------------------------
+ 0x00, 0x02, 0x00, 21, // type = content object, length = 21
+ // ------------------------
+ 0x00, 0x00, 0x00, 0x11, // type = name, length = 17
+ 0x00, 0x03, 0x00, 0x05, // type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 'o',
+ 0xF0, 0x00, 0x00, 0x04, // type = app, length = 4
+ 'o', 'u', 'c', 'h', // "ouch"
+ // ------------------------
+ 0x00, 0x03, 0x00, 4, // validation alg, length = 4
+ 0x00, 0x02, 0x00, 0x00, // CRC32C
+ // ------------------------
+ 0x00, 0x04, 0x00, 4, // validation payload
+ 0x2C, 0x3C, 0xC0, 0xAF // 2C3CC0AF
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_content_nameA_crc32c)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_E2EFRAG, .bodyManifest = false, .extent = { 12, 20 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_RecommendedCacheTime, .bodyManifest = false, .extent = { 36, 8 } },
+
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_CONTENTOBJECT, .bodyManifest = true, .extent = { 48, 21 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_NAME, .bodyManifest = true, .extent = { 52, 17 } },
+
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_ValidationAlg, .bodyManifest = true, .extent = { 73, 4 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_SIGBITS, .bodyManifest = true, .extent = { 81, 4 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_content_nameA_crc32c_truthTable TABLEENTRY(v1_content_nameA_crc32c, TLV_ERR_NO_ERROR)
+
+#define v1_content_nameA_crc32c_URI "lci:/3=hello/0xf000=ouch"
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h
new file mode 100644
index 00000000..ef37fb5e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h
@@ -0,0 +1,181 @@
+/*
+ * 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 interest_nameA_crc32c.h
+ * @brief Interest with CRC validation
+ *
+ * Signature generated using "openssl sha -sign test_rsa_key.pem -sha256 -binary y > sig", where "y" is
+ * generated from the "xxd -r" of the message hex dump. You need to manually edit "y" so it only
+ * contains the parts begin signed. Then use "xxd -i sig" to get the byte array.
+ *
+ * you can get the dump from the "write_packets" command. here's the detailed steps:
+ *
+ * 1) execute ./write_packets
+ * 2) xxd -r -c 8 v1_content_nameA_keyid1_rsasha256.txt > y
+ * 3) vim -b y
+ * 4) :%!xxd -p -c 16
+ * 5) Delete the frist 32 bytes (2 lines). The first line should now be:
+ * 0002003a000000110002000568656c6c
+ * 6) Delete the last 132 bytes (9 lines, 8 full lines plus the last 4 byte line)
+ * The last line in the file should now be:
+ * 0f3592ae7027fbd2e41e270203010001
+ * What's left is the part to be signed.
+ * 7) :%!xxd -r -p -c 16
+ * 8) :wq
+ * 9) Copy the PEM blocks below and put them in the file "key.pem". Make sure to remove
+ * any leading whitespace. If you get an error in the next command like
+ * "53999:error:0906D06C:PEM routines:PEM_read_bio:no start ... 648:Expecting: ANY PRIVATE KEY" then
+ * you most likely have leading whitespace. Make sure all lines are flush left.
+ * 10) openssl sha -sign key.pem -sha256 -binary y > sig
+ * 11) xxd -i sig
+ * 12) Put the byte array from (11) in the Validation Payload. Verify the length, it should be
+ * 128 bytes. If not, fixup the length of the ValidatonPayload and the PacketLength.
+ *
+ */
+
+/*
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIICXAIBAAKBgQCn1pPF8XPGErX6ecXvGIvvqs0EAY+Ddz+xZqFauTkqsj4w+xH8
+ * V/yd0S938Kt3rWYsJsibUW9pvyYQBinuy7AsXpEOJEKN5nWgTgRDDD5MBnRnrYTD
+ * 6PTFlHPEnyWoQga/RRnimBw2oUNNm3EI4YLf4k8qPD0PNZKucCf70uQeJwIDAQAB
+ * AoGAVOYPA/7aIGSQlu4IOKTDDG3qnM8pSEgG+PbAQgMVrspQ+TfXZj0ftLj++P3N
+ * zpDw8P6BVUfBQs2FNG/ZwEhaiZVgJAl7cIAxJ9Ac+1oZYSgGyJfb3u9iWvkbMOoj
+ * 83Inx5yyN+Qmk5zceH4pOC5D5cDAuGGZ740Euv4o2/2O3qECQQDTmWZw021PvEbA
+ * r18O1YfZGxO3zFCwFXCpnHvtSMbP+MXAG5Gt47wZt4Vx1rX9k78beeCUitwqp3d3
+ * ZI+YlUu3AkEAyw5wssQsJty/n2FL8DbJN3UzUhkcaCFYrKz3RtFye9wu+Bw0TxPC
+ * 3jhFVcynm3nH3ZJN0JsnsPnHXuoQToShEQJATXC51hb6zZC5UDGel348fo9zUvP6
+ * n8bo+ZoknL3izSBdtyYf1cUgBUVuGDCdYFWfPn4HXDXJx+6MQWzTRON21wJBAMZL
+ * U8M/z94jtP3wBjiPR/Dggz2pSBRofDAkuVZvM13BqByjbnHK2oIocY1YTlWGl6fJ
+ * ODR/UEODqS8HZOVIoAECQANcuvVnqDixSIl2ySZvydQytv4DKTbvE0nYSRroYIlJ
+ * PTOBPy8ynIUkJwc2E1BsLl7V8gO62a5O0ntTwBMnPSQ=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN PUBLIC KEY-----
+ * MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn1pPF8XPGErX6ecXvGIvvqs0E
+ * AY+Ddz+xZqFauTkqsj4w+xH8V/yd0S938Kt3rWYsJsibUW9pvyYQBinuy7AsXpEO
+ * JEKN5nWgTgRDDD5MBnRnrYTD6PTFlHPEnyWoQga/RRnimBw2oUNNm3EI4YLf4k8q
+ * PD0PNZKucCf70uQeJwIDAQAB
+ * -----END PUBLIC KEY-----
+ */
+
+#ifndef v1_content_nameA_keyid1_rsasha256_h
+#define v1_content_nameA_keyid1_rsasha256_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h>
+
+/**
+ * A well formed interest with only a name
+ */
+
+
+__attribute__((unused))
+static uint8_t v1_content_nameA_keyid1_rsasha256[] = {
+ 0x01, 0x01, 0x01, 0xB4,// ver = 1, type = content object, length = 436
+ 0x00, 0x00, 0x00, 32, // HopLimit = 0, reserved = 0, header length = 32
+ // ------------------------
+ 0x00, 0x04, 0x00, 20, // ContentObject Fragment, length = 20
+ 0x12, 0x23, 0x34, 0x45,
+ 0x56, 0x67, 0x78, 0x89,// fragid 0x1223344556677889
+ 0x05, 0xDC, 0x01, 0x00,// MTU 1500, fragcnt 1, fragnum 0
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08,// interest fragment 0x0102030405060708
+ // ------------------------
+ 0x00, 0x02, 0x00, 58, // type = content object, length = 58
+ // ------------------------
+ 0x00, 0x00, 0x00, 17, // type = name, length = 17
+ 0x00, 0x03, 0x00, 0x05,// type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 'o',
+ 0xF0, 0x00, 0x00, 0x04,// type = app, length = 4
+ 'o', 'u', 'c', 'h', // "ouch"
+ // ------------------------
+ 0x00, 0x05, 0x00, 1, // PayloadType
+ 1, // type 1 = key
+ 0x00, 0x06, 0x00, 0x08,// expiry time in msec
+ 0x00, 0x00, 0x01, 0x43,// 1,388,534,400,000 msec
+ 0x4B, 0x19, 0x84, 0x00,
+ 0x00, 0x19, 0x00, 4, // end chunk number
+ 0x06, 0x05, 0x04, 0x03,
+ // ------------------------
+ 0x00, 0x01, 0x00, 8, // payload, length = 8
+ 0x73, 0x75, 0x72, 0x70,
+ 0x72, 0x69, 0x73, 0x65,
+ // ------------------------
+ 0x00, 0x03, 0x00, 206, // validation alg, length = 206
+ 0x00, 0x06, 0x00, 202, // RSA-SHA256, length = 162 + 4 + 32 + 4 = 202
+ 0x00, 0x09, 0x00, 32, // type = keyid, length = 32
+ 0x5c, 0x23, 0x4c, 0x28,
+ 0x50, 0xda, 0x20, 0x7b,
+ 0x88, 0x25, 0x8b, 0xf3,
+ 0x62, 0x61, 0x96, 0xd8,
+ 0xf0, 0x60, 0x76, 0x38,
+ 0xa2, 0xd4, 0xe0, 0xe2,
+ 0x49, 0xb2, 0xa9, 0xaf,
+ 0xce, 0xb8, 0x85, 0x59,
+ 0x00, 0x0B, 0x00, 162, // public key, length = 162
+ 0x30, 0x81, 0x9f, 0x30,0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01,0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
+ 0x89, 0x02, 0x81, 0x81,0x00, 0xa7, 0xd6, 0x93, 0xc5, 0xf1, 0x73, 0xc6,
+ 0x12, 0xb5, 0xfa, 0x79,0xc5, 0xef, 0x18, 0x8b, 0xef, 0xaa, 0xcd, 0x04,
+ 0x01, 0x8f, 0x83, 0x77,0x3f, 0xb1, 0x66, 0xa1, 0x5a, 0xb9, 0x39, 0x2a,
+ 0xb2, 0x3e, 0x30, 0xfb,0x11, 0xfc, 0x57, 0xfc, 0x9d, 0xd1, 0x2f, 0x77,
+ 0xf0, 0xab, 0x77, 0xad,0x66, 0x2c, 0x26, 0xc8, 0x9b, 0x51, 0x6f, 0x69,
+ 0xbf, 0x26, 0x10, 0x06,0x29, 0xee, 0xcb, 0xb0, 0x2c, 0x5e, 0x91, 0x0e,
+ 0x24, 0x42, 0x8d, 0xe6,0x75, 0xa0, 0x4e, 0x04, 0x43, 0x0c, 0x3e, 0x4c,
+ 0x06, 0x74, 0x67, 0xad,0x84, 0xc3, 0xe8, 0xf4, 0xc5, 0x94, 0x73, 0xc4,
+ 0x9f, 0x25, 0xa8, 0x42,0x06, 0xbf, 0x45, 0x19, 0xe2, 0x98, 0x1c, 0x36,
+ 0xa1, 0x43, 0x4d, 0x9b,0x71, 0x08, 0xe1, 0x82, 0xdf, 0xe2, 0x4f, 0x2a,
+ 0x3c, 0x3d, 0x0f, 0x35,0x92, 0xae, 0x70, 0x27, 0xfb, 0xd2, 0xe4, 0x1e,
+ 0x27, 0x02, 0x03, 0x01,0x00, 0x01,
+ // ------------------------
+ 0x00, 0x04, 0x00, 128, // validation payload, length = 128
+ 0x03, 0x46, 0xee, 0xb7,0x30, 0x1c, 0xea, 0x13, 0x0c, 0xce, 0x83, 0x5b,
+ 0x7b, 0x4f, 0xf5, 0x83,0x37, 0x08, 0x7f, 0xe0, 0xe1, 0xc9, 0x70, 0x09,
+ 0x5e, 0xc2, 0x1c, 0xd3,0x74, 0xbb, 0xbd, 0x72, 0x35, 0xa4, 0x1b, 0x0f,
+ 0x3d, 0x04, 0x5e, 0xf7,0xc1, 0xdf, 0xea, 0xc3, 0x50, 0x47, 0x14, 0xf9,
+ 0xb7, 0xbb, 0x42, 0xf9,0x3e, 0xaa, 0x49, 0xd2, 0x9f, 0xd1, 0xab, 0xf6,
+ 0xda, 0x32, 0x4a, 0xb1,0xb9, 0x69, 0x91, 0x57, 0x43, 0x5d, 0x06, 0xcf,
+ 0x1d, 0x9f, 0x7c, 0x28,0xee, 0x35, 0xaa, 0xd0, 0xb2, 0x8d, 0x34, 0x09,
+ 0xcd, 0xdb, 0x01, 0xf7,0xda, 0xe8, 0x59, 0x98, 0x4e, 0x59, 0xfa, 0x13,
+ 0xd0, 0xd1, 0x54, 0x8e,0x64, 0x8c, 0xc6, 0xd7, 0x6b, 0xc5, 0x89, 0xeb,
+ 0x37, 0x8f, 0x53, 0x04,0xba, 0x03, 0x05, 0xb4, 0x67, 0x73, 0xe1, 0x51,
+ 0x59, 0x12, 0xbc, 0x25,0xaa, 0xa2, 0xc1, 0x18
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_content_nameA_keyid1_rsasha256)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_E2EFRAG, .bodyManifest = false, .extent = { 12, 20 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_CONTENTOBJECT, .bodyManifest = true, .extent = { 36, 58 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_NAME, .bodyManifest = true, .extent = { 40, 17 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_PAYLOADTYPE, .bodyManifest = true, .extent = { 61, 1 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_EXPIRY_TIME, .bodyManifest = true, .extent = { 66, 8 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_ENDSEGMENT, .bodyManifest = true, .extent = { 78, 4 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_PAYLOAD, .bodyManifest = true, .extent = { 86, 8 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_ValidationAlg, .bodyManifest = true, .extent = { 94, 206 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_KEYID, .bodyManifest = true, .extent = { 106, 32 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_PUBKEY, .bodyManifest = true, .extent = { 142, 162 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_SIGBITS, .bodyManifest = true, .extent = { 308, 128 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_content_nameA_keyid1_rsasha256_truthTable TABLEENTRY(v1_content_nameA_keyid1_rsasha256, TLV_ERR_NO_ERROR)
+
+#define v1_content_nameA_keyid1_rsasha256_URI "lci:/3=hello/0xf000=ouch"
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameless_nosig.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameless_nosig.h
new file mode 100644
index 00000000..f1fc59cb
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_nameless_nosig.h
@@ -0,0 +1,65 @@
+/*
+ * 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 v1_content_nameless_nosig.h
+ * @brief A v1 content object without a name
+ *
+ */
+
+#ifndef v1_content_nameless_nosig_h
+#define v1_content_nameless_nosig_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h>
+
+/**
+ * A well formed nameless V1 Content Object
+ */
+__attribute__((unused))
+static uint8_t v1_content_nameless_nosig[] = {
+ 0x01, 0x01, 0x00, 0x31, // ver = 1, type = content object, length = 0x31
+ 0x00, 0x00, 0x00, 0x08, // HopLimit = 0, reserved = 0, header length = 8
+ // ------------------------
+ 0x00, 0x02, 0x00, 37, // type = content object, length = 37
+ // ------------------------
+ 0x00, 0x05, 0x00, 1, // PayloadType
+ 1, // type 1 = key
+ 0x00, 0x06, 0x00, 0x08, // expiry time in msec
+ 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+ 0x4B, 0x19, 0x84, 0x00,
+ 0x00, 0x19, 0x00, 4, // end chunk number
+ 0x06, 0x05, 0x04, 0x03,
+ // ------------------------
+ 0x00, 0x01, 0x00, 8, // payload, length = 8
+ 0x73, 0x75, 0x72, 0x70,
+ 0x72, 0x69, 0x73, 0x65,
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_content_nameless_nosig)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_CONTENTOBJECT, .bodyManifest = true, .extent = { 12, 37 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_PAYLOADTYPE, .bodyManifest = true, .extent = { 17, 1 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_EXPIRY_TIME, .bodyManifest = true, .extent = { 22, 8 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_ENDSEGMENT, .bodyManifest = true, .extent = { 30, 4 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_PAYLOAD, .bodyManifest = true, .extent = { 41, 8 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_content_nameless_nosig_truthTable TABLEENTRY(v1_content_nameless_nosig, TLV_ERR_NO_ERROR)
+
+#endif // v1_content_nameless_nosig_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_no_payload.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_no_payload.h
new file mode 100644
index 00000000..ae439bf5
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_no_payload.h
@@ -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.
+ */
+
+/**
+ * @file v1_content_no_payload.h
+ * @brief Content Object without a payload TLV
+ *
+ *
+ */
+
+
+#ifndef CCNx_Common_v1_content_no_payload_h
+#define CCNx_Common_v1_content_no_payload_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h>
+
+__attribute__((unused))
+static uint8_t v1_content_no_payload[] = {
+ 0x01, 0x01, 0x00, 0x21,
+ 0x00, 0x00, 0x00, 0x08,
+ // -- content object
+ 0x00, 0x02, 0x00, 0x15,
+ // -- name
+ 0x00, 0x00, 0x00, 0x11,
+ 0x00, 0x03, 0x00, 0x02,
+ 0x6e, 0x6f,
+ 0x00, 0x03, 0x00, 0x07,
+ 0x70, 0x61, 0x79, 0x6c,
+ 0x6f, 0x61, 0x64
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_content_no_payload)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_CONTENTOBJECT, .bodyManifest = true, .extent = { 12, 21 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_content_no_payload_truthTable TABLEENTRY(v1_content_no_payload, TLV_ERR_NO_ERROR)
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_zero_payload.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_zero_payload.h
new file mode 100644
index 00000000..01f7a8b4
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_content_zero_payload.h
@@ -0,0 +1,57 @@
+/*
+ * 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 v1_content_zero_payload.h
+ * @brief Content Object with zero length payload
+ *
+ *
+ */
+
+
+#ifndef CCNx_Common_v1_content_zero_payload_h
+#define CCNx_Common_v1_content_zero_payload_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h>
+
+__attribute__((unused))
+static uint8_t v1_content_zero_payload[] = {
+ 0x01, 0x01, 0x00, 0x25,
+ 0x00, 0x00, 0x00, 0x08,
+ // -- content object
+ 0x00, 0x02, 0x00, 0x19,
+ // -- name
+ 0x00, 0x00, 0x00, 0x11,
+ 0x00, 0x03, 0x00, 0x02,
+ 0x6e, 0x6f,
+ 0x00, 0x03, 0x00, 0x07,
+ 0x70, 0x61, 0x79, 0x6c,
+ 0x6f, 0x61, 0x64,
+ // -- payload
+ 0x00, 0x01, 0x00, 0x00,
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_content_zero_payload)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_OBJ_CONTENTOBJECT, .bodyManifest = true, .extent = { 12, 25 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_content_zero_payload_truthTable TABLEENTRY(v1_content_zero_payload, TLV_ERR_NO_ERROR)
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route.h
new file mode 100644
index 00000000..9bcf7dfc
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route.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 v1_cpi_add_route.h
+ * @brief A hand-encoded CPI packet to add a route
+ *
+ * The v1 old-style control packet is a fixed header plus a tlv container 0xBEEF with a "value" of the CPI JSON string.
+ * The packet type is 0xA4.
+ *
+ */
+
+#ifndef TransportRTA_v1_cpi_AddRoute_h
+#define TransportRTA_v1_cpi_AddRoute_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_CPISchema.h>
+
+__attribute__((unused))
+static uint8_t v1_cpi_add_route[] = "\x01\xA4\x00\xA7"
+ "\x00\x00\x00\x08"
+ "\xBE\xEF\x00\x9A"
+ "{\"CPI_REQUEST\":{\"SEQUENCE\":22,\"REGISTER\":{\"PREFIX\":\"lci:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}}}";
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_cpi_add_route)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_CPI_PAYLOAD, .bodyManifest = true, .extent = { 12, 155 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_cpi_add_route_truthTable TABLEENTRY(v1_cpi_add_route, TLV_ERR_NO_ERROR)
+
+#define v1_cpi_add_route_PrefixUri "lci:/howdie/stranger"
+#define v1_cpi_add_route_Sequence 22
+#define v1_cpi_add_route_Interface 55
+#endif // TransportRTA_cpi_AddRoute_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route_crc32c.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route_crc32c.h
new file mode 100644
index 00000000..e31cfc85
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route_crc32c.h
@@ -0,0 +1,78 @@
+/*
+ * 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 v1_cpi_add_route.h
+ * @brief A hand-encoded CPI packet to add a route
+ *
+ * The v1 old-style control packet is a fixed header plus a tlv container 0xBEEF with a "value" of the CPI JSON string.
+ * The packet type is 0xA4.
+ *
+ * This control packet has a CRC32C MIC on it. Otherwise, same as v1_cpi_add_route.h
+ *
+ * Ground truth set derived from CRC RevEng http://reveng.sourceforge.net
+ * e.g. reveng -c -m CRC-32C 313233343536373839 gives the canonical check value 0xe306928e
+ *
+ * You can also calcaulate CRC32C online at http://www.zorc.breitbandkatze.de/crc.html using
+ * CRC polynomial 0x1EDC6F41, init 0xFFFFFFFF, final 0xFFFFFFFF, reverse data bytes (check),
+ * and reverse CRC result before final XOR (check).
+ *
+ * you can get the packet dump from the "write_packets" command. here's the detailed steps.
+ * The -c size of 4 in steps 4 and 7 are chosen to make it easy to delete the right number of lines.
+ * there's nothing magic about the "4".
+ *
+ * 1) execute ./write_packets
+ * 2) xxd -r -c 8 v1_cpi_add_route_crc32c.txt > y
+ * 3) Delete the first 8 bytes and last 16 bytes and display has a hex string
+ * tail -c +9 y | head -c 158 | xxd -p -c 256
+ * The string should be "beef...077d7d7d"
+ * 4) The string for this packet is too long for the website. Use another tool such as reveng.
+ * 5) The answer should be 78fd926a (the reveng answer will be byte reversed)
+ * 6) Put the byte array from (5) in the Validation Payload.
+ *
+ */
+
+#ifndef TransportRTA_v1_v1_cpi_AddRoute_crc32c_h
+#define TransportRTA_v1_v1_cpi_AddRoute_crc32c_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_CPISchema.h>
+
+__attribute__((unused))
+static uint8_t v1_cpi_add_route_crc32c[] = "\x01\xA4\x00\xB7"
+ "\x00\x00\x00\x08"
+ "\xBE\xEF\x00\x9A"
+ "{\"CPI_REQUEST\":{\"SEQUENCE\":22,\"REGISTER\":{\"PREFIX\":\"lci:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}}}"
+ "\x00\x03\x00\x04"
+ "\x00\x02\x00\x00"
+ "\x00\x04\x00\x04"
+ "\x78\xfd\x92\x6a";
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_cpi_add_route_crc32c)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_CPI_PAYLOAD, .bodyManifest = true, .extent = { 12, 155 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_CPI_ValidationAlg, .bodyManifest = true, .extent = { 171, 4 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_CPI_SIGBITS, .bodyManifest = true, .extent = { 178, 4 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_cpi_add_route_crc32c_truthTable TABLEENTRY(v1_cpi_add_route_crc32c, TLV_ERR_NO_ERROR)
+
+#define v1_cpi_add_route_crc32c_PrefixUri "lci:/howdie/stranger"
+#define v1_cpi_add_route_crc32c_Sequence 22
+#define v1_cpi_add_route_crc32c_Interface 55
+#endif // TransportRTA_cpi_AddRoute_h
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h
new file mode 100755
index 00000000..f6524ad1
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h
@@ -0,0 +1,102 @@
+/*
+ * 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 v1_interest_all_fields.h
+ * @brief A hand-encoded v1 interest in wireformat with all Interest fields.
+ *
+ * <#Detailed Description#>
+ *
+ */
+
+#ifndef CCNx_Common_v1_interest_all_fields_h
+#define CCNx_Common_v1_interest_all_fields_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+
+/**
+ * A well formed interest with all allowed Interest fields
+ */
+__attribute__((unused))
+static uint8_t v1_interest_all_fields[] = {
+ 0x01, 0x00, 0x00, 156, // ver = 1, type = interest, length = 156
+ 0x20, 0x00, 0x11, 14, // HopLimit = 32, reserved = 0, flags = 0x11, header length = 14
+ // ------------------------
+ 0x00, 0x01, 0x00, 2, // Interest Lifetime (2 bytes)
+ 0xEA, 0xEB,
+ // ------------------------
+ 0x00, 0x01, 0x00, 138, // type = interest, length = 138
+ // ------------------------
+ 0x00, 0x00, 0x00, 45, // type = name, length = 45
+ 0x00, 0x03, 0x00, 4, // type = binary, length = 4
+ 'c', 'o', 'o', 'l', // "cool"
+ // ----- segment 2 --------
+ 0x00, 0x02, 0x00, 33, // type = payload id, length = 33
+ 0x01, // payloadID type = sha256
+ 0x89, 0x87, 0x69, 0xfc, // hash bytes based on payload
+ 0x8c, 0xff, 0x16, 0xff,
+ 0x3d, 0xfc, 0xe7, 0xfa,
+ 0x02, 0xd2, 0x6d, 0x26,
+ 0xf0, 0x91, 0x86, 0x27,
+ 0xcf, 0x18, 0xc1, 0x9b,
+ 0x0b, 0x5f, 0xe3, 0x93,
+ 0xce, 0x1a, 0xa3, 0x56,
+ // ------------------------
+ 0x00, 0x02, 0x00, 36, // type = keyid restriction, length = 36
+ 0x00, 0x01, 0x00, 0x20, // SHA256 hash, length 32
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf,
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf,
+ // ------------------------
+ 0x00, 0x03, 0x00, 36, // type = hash restriction, length = 36
+ 0x00, 0x01, 0x00, 0x20, // SHA256 hash, length 32
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb,
+ 0xcc, 0xcd, 0xce, 0xcf,
+ // ------------------------
+ 0x00, 0x01, 0x00, 5, // type = payload, length = 5
+ 0xD0, 0xD1, 0xD2, 0xD3,
+ 0xD4,
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_interest_all_fields)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_LIFETIME, .bodyManifest = false, .extent = { 12, 2 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_INTEREST, .bodyManifest = true, .extent = { 18, 138 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_NAME, .bodyManifest = true, .extent = { 22, 45 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_KEYID, .bodyManifest = true, .extent = { 71, 36 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_OBJHASH, .bodyManifest = true, .extent = { 111, 36 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_PAYLOAD, .bodyManifest = true, .extent = { 151, 5 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_interest_all_fields_truthTable TABLEENTRY(v1_interest_all_fields, TLV_ERR_NO_ERROR)
+
+#define v1_interest_all_fields_URI "lci:/3=cool/2=\x01\x89\x87\x69\xfc\x8c\xff\x16\xff\x3d\xfc\xe7\xfa\x02\xd2\x6d\x26\xf0\x91\x86\x27\xcf\x18\xc1\x9b\x0b\x5f\xe3\x93\xce\x1a\xa3\x56"
+#define v1_interest_all_fields_Lifetime 0xEAEB
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_bad_message_length.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_bad_message_length.h
new file mode 100644
index 00000000..650c770e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_bad_message_length.h
@@ -0,0 +1,57 @@
+/*
+ * 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 v1_interest_all_fields.h
+ * @brief A hand-encoded v1 interest in wireformat with all Interest fields.
+ *
+ * The Interest TLV length goes beyond the end of the packet
+ *
+ */
+
+#ifndef CCNx_Common_v1_interest_bad_message_length_h
+#define CCNx_Common_v1_interest_bad_message_length_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+
+/**
+ * A well formed interest with all allowed Interest fields
+ */
+__attribute__((unused))
+static uint8_t v1_interest_bad_message_length[] = {
+ 0x01, 0x00, 0x00, 30, // ver = 1, type = interest, length = 30
+ 0x20, 0x00, 0x11, 14, // HopLimit = 31, reserved = 0, flags = 0x11, header length = 14
+ // ------------------------
+ 0x00, 0x01, 0x00, 2, // Interest Lifetime (2 bytes)
+ 0xEA, 0xEB,
+ // ------------------------
+ 0x00, 0x01, 0x00, 13, // type = interest, length = 13 (1 byte too far)
+ // ------------------------
+ 0x00, 0x00, 0x00, 8, // type = name, length = 8
+ 0x00, 0x03, 0x00, 4, // type = binary, length = 4
+ 'c', 'o', 'o', 'l', // "cool"
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_interest_bad_message_length)[] =
+{
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_interest_bad_message_length_truthTable TABLEENTRY(v1_interest_bad_message_length, TLV_ERR_TOO_LONG)
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_bad_validation_alg.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_bad_validation_alg.h
new file mode 100644
index 00000000..9c4c3117
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_bad_validation_alg.h
@@ -0,0 +1,74 @@
+/*
+ * 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 v1_interest_bad_validation_alg.h
+ * @brief Interest with CRC validation
+ *
+ * This is an error packet, the ValidationAlg TLV does not have the correct type
+ *
+ */
+
+#ifndef testdata_v1_interest_bad_validation_alg
+#define testdata_v1_interest_bad_validation_alg
+
+/**
+ * A well formed interest with only a name
+ */
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+
+__attribute__((unused))
+static uint8_t v1_interest_bad_validation_alg[] = {
+ 0x01, 0x00, 0x00, 65, // ver = 1, type = interest, length = 65
+ 0x20, 0x00, 0x00, 24, // HopLimit = 32, reserved = 0, header length = 24
+ // ------------------------
+ 0x00, 0x03, 0x00, 12, // Interest Fragment
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, // fragment 0x0102030405060708
+ 0x05, 0xDC, 0x00, 0x00, // MTU 1500, fragcnt 0, fragnum 0
+ // ------------------------
+ 0x00, 0x01, 0x00, 0x15, // type = interest, length = 21
+ // ------------------------
+ 0x00, 0x00, 0x00, 0x11, // type = name, length = 17
+ 0x00, 0x03, 0x00, 0x05, // type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 'o',
+ 0xF0, 0x00, 0x00, 0x04, // type = app, length = 4
+ 'o', 'u', 'c', 'h', // "ouch"
+ // ------------------------
+ 0x00, 0xFF, 0x00, 4, // Not "0x03" validation alg length = 4
+ 0x00, 0xFF, 0x00, 0x00, // unknown validation alg
+ // ------------------------
+ 0x00, 0x04, 0x00, 4, // validation payload
+ 0x6A, 0xD7, 0xB1, 0xF2 // 6AD7B1F2
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_interest_bad_validation_alg)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_E2EFRAG, .bodyManifest = false, .extent = { 12, 12 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_INTEREST, .bodyManifest = true, .extent = { 24, 25 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_NAME, .bodyManifest = true, .extent = { 32, 17 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_ValidationAlg, .bodyManifest = true, .extent = { 53, 4 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_ValidationPayload, .bodyManifest = true, .extent = { 61, 4 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_interest_bad_validation_alg_truthTable TABLEENTRY(v1_interest_bad_validation_alg, TLV_ERR_NO_ERROR)
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA.h
new file mode 100644
index 00000000..4bee1e40
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA.h
@@ -0,0 +1,75 @@
+/*
+ * 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 v1_interest_nameA.h
+ * @brief A basic interest
+ *
+ * A basic Interest with a fragmentation header and Name.
+ *
+ */
+
+#ifndef testdata_interest_nameA_h
+#define testdata_interest_nameA_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+
+/**
+ * A well formed interest with only a name
+ */
+
+
+__attribute__((unused))
+static uint8_t v1_interest_nameA[] = {
+ 0x01, 0x00, 0x00, 61, // ver = 1, type = interest, length = 61
+ 0x20, 0x00, 0x00, 36, // HopLimit = 31, reserved = 0, header length = 36
+ // ------------------------
+ // ------------------------
+ 0x00, 0x03, 0x00, 12, // Interest Fragment
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, // fragment 0x0102030405060708
+ 0x05, 0xDC, 0x00, 0x00, // MTU 1500, fragcnt 0, fragnum 0
+ // ------------------------
+ 0x00, 0x01, 0x00, 8, // Interest Lifetime
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0F, 0xA0, // 4000 milli-seconds
+ // ------------------------
+ 0x00, 0x01, 0x00, 0x15, // type = interest, length = 21
+ // ------------------------
+ 0x00, 0x00, 0x00, 0x11, // type = name, length = 17
+ 0x00, 0x03, 0x00, 0x05, // type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 'o',
+ 0xF0, 0x00, 0x00, 0x04, // type = app, length = 4
+ 'o', 'u', 'c', 'h', // "ouch"
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_interest_nameA)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_E2EFRAG, .bodyManifest = false, .extent = { 12, 12 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_LIFETIME, .bodyManifest = false, .extent = { 28, 8 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_INTEREST, .bodyManifest = false, .extent = { 40, 21 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_NAME, .bodyManifest = true, .extent = { 44, 17 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_interest_nameA_truthTable TABLEENTRY(v1_interest_nameA, TLV_ERR_NO_ERROR)
+
+#define v1_interest_nameA_URI "lci:/3=hello/0xf000=ouch"
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_badcrc32c.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_badcrc32c.h
new file mode 100644
index 00000000..6af04f42
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_badcrc32c.h
@@ -0,0 +1,76 @@
+/*
+ * 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 interest_nameA_badcrc32c.h
+ * @brief Interest with CRC validation
+ *
+ * Has incorrect CRC32C payload
+ *
+ */
+
+#ifndef testdata_interest_nameA_badcrc32c_h
+#define testdata_interest_nameA_badcrc32c_h
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+
+/**
+ * A well formed interest with only a name
+ */
+
+__attribute__((unused))
+static uint8_t v1_interest_nameA_badcrc32c[] = {
+ 0x01, 0x00, 0x00, 41, // ver = 1, type = interest, length = 65
+ 0x20, 0x00, 0x00, 24, // HopLimit = 31, reserved = 0, header length = 24
+ // ------------------------
+ 0x00, 0x03, 0x00, 0x0C, // Interest Fragment
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, // fragment 0x0102030405060708
+ 0x05, 0xDC, 0x00, 0x00, // MTU 1500, fragcnt 0, fragnum 0
+ // ------------------------
+ 0x00, 0x01, 0x00, 0x15, // type = interest, length = 21
+ // ------------------------
+ 0x00, 0x00, 0x00, 0x11, // type = name, length = 17
+ 0x00, 0x03, 0x00, 0x05, // type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 'o',
+ 0xF0, 0x00, 0x00, 0x04, // type = app, length = 4
+ 'o', 'u', 'c', 'h', // "ouch"
+ // ------------------------
+ 0x00, 0x03, 0x00, 4, // validation alg, length = 4
+ 0x00, 0x02, 0x00, 0x00, // CRC32C
+ // ------------------------
+ 0x00, 0x04, 0x00, 4, // validation payload
+ 0x00, 0x00, 0x00, 0x00 // invalid CRC32C
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_interest_nameA_badcrc32c)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_E2EFRAG, .bodyManifest = false, .extent = { 12, 12 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_INTEREST, .bodyManifest = true, .extent = { 20, 21 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_NAME, .bodyManifest = true, .extent = { 24, 17 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_ValidationAlg, .bodyManifest = true, .extent = { 45, 4 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_ValidationPayload, .bodyManifest = true, .extent = { 53, 4 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_interest_nameA_badcrc32c_truthTable TABLEENTRY(v1_interest_nameA_badcrc32c, TLV_ERR_NO_ERROR)
+
+#define v1_interest_nameA_badcrc32c_URI "lci:/3=hello/0xf000=ouch"
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_crc32c.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_crc32c.h
new file mode 100644
index 00000000..64edf560
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_nameA_crc32c.h
@@ -0,0 +1,102 @@
+/*
+ * 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 interest_nameA_crc32c.h
+ * @brief Interest with CRC validation
+ *
+ *
+ * Ground truth set derived from CRC RevEng http://reveng.sourceforge.net
+ * e.g. reveng -c -m CRC-32C 313233343536373839 gives the canonical check value 0xe306928e (the output will be backwards)
+ *
+ * You can also calcaulate CRC32C online at http://www.zorc.breitbandkatze.de/crc.html using
+ * CRC polynomial 0x1EDC6F41, init 0xFFFFFFFF, final 0xFFFFFFFF, reverse data bytes (check),
+ * and reverse CRC result before final XOR (check).
+ *
+ * you can get the packet dump from the "write_packets" command. here's the detailed steps.
+ * The -c size of 8 in steps 4 and 7 are chosen to make it easy to delete the right number of lines.
+ * there's nothing magic about the "8".
+ *
+ * 1) execute ./write_packets
+ * 2) xxd -r -c 8 v1_interest_nameA_crc32c.txt > y
+ * 3) Delete the first 24 bytes and last 8 bytes and display as a URI-escaped hex string
+ * head -c 57 y | tail -c +25 | xxd -p -c 256 | sed 's/[0-9a-f]\{2\}/%&/g'
+ * The string should be "00010015...00020000"
+ * 4) Copy the hex string to the website and use the settings specified above (don't use 0x in front
+ * of any hex strings). IMPORTANT: you need to %-escape each hex byte!! Click "compute!"
+ * 5) The answer should be 6AD7B1F2
+ * 6) Put the byte array from (5) in the Validation Payload.
+ *
+ */
+
+#ifndef testdata_interest_nameA_crc32c_h
+#define testdata_interest_nameA_crc32c_h
+
+/**
+ * A well formed interest with only a name
+ */
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+
+#define NAME_A_CRC32_PACKET(_type, _code) \
+ { \
+ 0x01, _type, 0x00, 65, /* ver = 1, type = interest, length = 65 */ \
+ 0x20, _code, 0x00, 24, /* HopLimit = 32, reserved = 0, header length = 24*/ \
+ /* ------------------------ */ \
+ 0x00, 0x03, 0x00, 12, /* Interest Fragment */ \
+ 0x01, 0x02, 0x03, 0x04, \
+ 0x05, 0x06, 0x07, 0x08, /* fragment 0x0102030405060708 */ \
+ 0x05, 0xDC, 0x00, 0x00, /* MTU 1500, fragcnt 0, fragnum 0 */ \
+ /* ------------------------ */ \
+ 0x00, 0x01, 0x00, 0x15, /* type = interest, length = 21 */ \
+ /* ------------------------ */ \
+ 0x00, 0x00, 0x00, 0x11, /* type = name, length = 17 */ \
+ 0x00, 0x03, 0x00, 0x05, /* type = binary, length = 5 */ \
+ 'h', 'e', 'l', 'l', /* "hello" */ \
+ 'o', \
+ 0xF0, 0x00, 0x00, 0x04, /* type = app, length = 4 */ \
+ 'o', 'u', 'c', 'h', /* "ouch" */ \
+ /* ------------------------ */ \
+ 0x00, 0x03, 0x00, 4, /* validation alg, length = 4 */ \
+ 0x00, 0x02, 0x00, 0x00, /* CRC32C */ \
+ /* ------------------------ */ \
+ 0x00, 0x04, 0x00, 4, /* validation payload */ \
+ 0xD0, 0x98, 0x73, 0x7C, /* D098737C */ \
+ }
+
+__attribute__((unused))
+static uint8_t v1_interest_nameA_crc32c[] = NAME_A_CRC32_PACKET(0x00, 0x00);
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_interest_nameA_crc32c)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_E2EFRAG, .bodyManifest = false, .extent = { 12, 12 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_INTEREST, .bodyManifest = true, .extent = { 24, 25 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_NAME, .bodyManifest = true, .extent = { 32, 17 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_ValidationAlg, .bodyManifest = true, .extent = { 53, 4 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_ValidationPayload, .bodyManifest = true, .extent = { 61, 4 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+__attribute__((unused))
+static uint8_t v1_interest_nameA_crc32c_returned[] = NAME_A_CRC32_PACKET(0x02, 0x03); //InterestReturn & NoResource
+
+#define v1_interest_nameA_crc32c_truthTable TABLEENTRY(v1_interest_nameA_crc32c, TLV_ERR_NO_ERROR)
+
+#define v1_interest_nameA_crc32c_URI "lci:/3=hello/0xf000=ouch"
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_validation_alg_overrun.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_validation_alg_overrun.h
new file mode 100644
index 00000000..8f3b55a5
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_interest_validation_alg_overrun.h
@@ -0,0 +1,74 @@
+/*
+ * 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 v1_interest_validation_alg_overrun.h
+ * @brief Interest with CRC validation
+ *
+ * This is an error packet. The length of the Validation TLV runs past the end of the packet.
+ *
+ */
+
+#ifndef testdata_v1_interest_validation_alg_overrun
+#define testdata_v1_interest_validation_alg_overrun
+
+/**
+ * A well formed interest with only a name
+ */
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+
+__attribute__((unused))
+static uint8_t v1_interest_validation_alg_overrun[] = {
+ 0x01, 0x00, 0x00, 65, // ver = 1, type = interest, length = 65
+ 0x20, 0x00, 0x00, 24, // HopLimit = 32, reserved = 0, header length = 24
+ // ------------------------
+ 0x00, 0x03, 0x00, 12, // Interest Fragment
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, // fragment 0x0102030405060708
+ 0x05, 0xDC, 0x00, 0x00, // MTU 1500, fragcnt 0, fragnum 0
+ // ------------------------
+ 0x00, 0x01, 0x00, 0x15, // type = interest, length = 21
+ // ------------------------
+ 0x00, 0x00, 0x00, 0x11, // type = name, length = 17
+ 0x00, 0x03, 0x00, 0x05, // type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 'o',
+ 0xF0, 0x00, 0x00, 0x04, // type = app, length = 4
+ 'o', 'u', 'c', 'h', // "ouch"
+ // ------------------------
+ 0x00, 0x03, 0x00, 255, // Validation Alg, length = 255
+ 0x00, 0xFF, 0x00, 0x00, // unknown validation alg
+ // ------------------------
+ 0x00, 0x04, 0x00, 4, // validation payload
+ 0x6A, 0xD7, 0xB1, 0xF2 // 6AD7B1F2
+};
+
+__attribute__((unused))
+static TruthTableEntry
+TRUTHTABLENAME(v1_interest_validation_alg_overrun)[] =
+{
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_E2EFRAG, .bodyManifest = false, .extent = { 12, 12 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_INTEREST, .bodyManifest = true, .extent = { 24, 25 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_NAME, .bodyManifest = true, .extent = { 32, 17 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_ValidationAlg, .bodyManifest = true, .extent = { 53, 4 } },
+ { .wellKnownType = true, .indexOrKey = V1_MANIFEST_INT_ValidationPayload, .bodyManifest = true, .extent = { 61, 4 } },
+ { .wellKnownType = false, .indexOrKey = T_INVALID, .extent = { 0, 0 } },
+};
+
+#define v1_interest_validation_alg_overrun_truthTable TABLEENTRY(v1_interest_validation_alg_overrun, TLV_ERR_TOO_LONG)
+
+#endif
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_testrig_truthSet.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_testrig_truthSet.h
new file mode 100644
index 00000000..f98de878
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_testrig_truthSet.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/**
+ * Contains tables of all the packets. May be used for automated testing. Also used by write_packets utility.
+ *
+ */
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+
+#include "v1_interest_nameA.h"
+#include "v1_interest_nameA_badcrc32c.h"
+#include "v1_interest_nameA_crc32c.h"
+#include "v1_interest_bad_validation_alg.h"
+#include "v1_interest_validation_alg_overrun.h"
+
+#include "v1_content_nameA_crc32c.h"
+#include "v1_content_nameA_keyid1_rsasha256.h"
+#include "v1_content_zero_payload.h"
+#include "v1_content_no_payload.h"
+
+#include "v1_cpi_add_route.h"
+#include "v1_cpi_add_route_crc32c.h"
+
+// terminated with NULL packet entry
+__attribute__((unused))
+static TruthTable v1_interests_truthSet [] = {
+ // tests in alphabetical order
+ v1_interest_nameA_truthTable,
+ v1_interest_nameA_badcrc32c_truthTable,
+ v1_interest_nameA_crc32c_truthTable,
+ v1_interest_bad_validation_alg_truthTable,
+ v1_interest_validation_alg_overrun_truthTable,
+ // the end of table marker
+ { .packet = NULL, .expectedError= 0, .entry = NULL }
+};
+
+// terminated with NULL packet entry
+__attribute__((unused))
+static TruthTable v1_contentObject_truthSet [] = {
+ v1_content_nameA_crc32c_truthTable,
+ v1_content_nameA_keyid1_rsasha256_truthTable,
+ v1_content_zero_payload_truthTable,
+ v1_content_no_payload_truthTable,
+
+ // the end of table marker
+ { .packet = NULL, .expectedError= 0, .entry = NULL }
+};
+
+__attribute__((unused))
+static TruthTable v1_cpi_truthSet [] = {
+ v1_cpi_add_route_truthTable,
+ v1_cpi_add_route_crc32c_truthTable,
+ // the end of table marker
+ { .packet = NULL, .expectedError= 0, .entry = NULL }
+};
diff --git a/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_testrig_truthTable.h b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_testrig_truthTable.h
new file mode 100755
index 00000000..32c954b7
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/schema_v1/testdata/v1_testrig_truthTable.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.
+ */
+
+
+/*
+ * testrig_truthTable.h
+ * TransportRTA
+ */
+
+#ifndef TransportRTA_testrig_truthTable_h
+#define TransportRTA_testrig_truthTable_h
+
+#include <ccnx/common/codec/schema_v1/testdata/v1_InterestSchema.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_ContentObjectSchema.h>
+//#include <ccnx/common/codec/schema_v1/testdata/v1_CPISchema.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <ccnx/common/codec/testdata/testdata_common.h>
+
+#endif