LONGBOW_TEST_CASE(Global, ccnxWireFormatMessage_HashProtectedRegion) { // >1234< const char string[] = "Hello dev null\n"; PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string)); size_t start = 5; size_t length = 4; CCNxWireFormatMessage *message = ccnxWireFormatMessage_FromContentObjectPacketType(CCNxTlvDictionary_SchemaVersion_V1, buffer); ccnxWireFormatMessage_SetProtectedRegionStart(message, start); ccnxWireFormatMessage_SetProtectedRegionLength(message, length); PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); PARCCryptoHash *hash = ccnxWireFormatMessage_HashProtectedRegion(message, hasher); // the correctness of the has is tested in _ccnxWireFormatFacadeV1_ComputeHash assertNotNull(hash, "Got null hash from a good packet"); ccnxWireFormatMessage_Release(&message); parcCryptoHash_Release(&hash); parcBuffer_Release(&buffer); parcCryptoHasher_Release(&hasher); }
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); }
TestData * testData_Create(void) { char keyidString[] = "the keyid"; char keyString[] = "Memory, all alone in the moonlight"; char certString[] = "The quick brown fox"; TestData *data = parcMemory_AllocateAndClear(sizeof(TestData)); assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData)); data->keyid = bufferFromString(sizeof(keyidString), keyidString); data->key = bufferFromString(sizeof(keyString), keyString); data->cert = bufferFromString(sizeof(certString), certString); data->keyname = ccnxName_CreateFromURI("lci:/lazy/dog"); PARCBuffer *bb_id = parcBuffer_Wrap("choo choo", 9, 0, 9); PARCKeyId *keyid = parcKeyId_Create(bb_id); parcBuffer_Release(&bb_id); PARCKey *key = parcKey_CreateFromDerEncodedPublicKey(keyid, PARCSigningAlgorithm_RSA, data->key); data->locatorByKey = ccnxKeyLocator_CreateFromKey(key); parcKey_Release(&key); parcKeyId_Release(&keyid); CCNxLink *link = ccnxLink_Create(data->keyname, NULL, NULL); data->locatorByName = ccnxKeyLocator_CreateFromKeyLink(link); ccnxLink_Release(&link); return data; }
LONGBOW_TEST_CASE(Dictionary, component_Codec_Tlv_Upcall_Read_Control) { TestData *data = longBowTestCase_GetClipBoardData(testCase); PARCBuffer *wireFormat = parcBuffer_Wrap(v1_cpi_add_route_crc32c, sizeof(v1_cpi_add_route_crc32c), 0, sizeof(v1_cpi_add_route_crc32c)); CCNxTlvDictionary *dictionary = ccnxWireFormatMessage_FromControlPacketType(CCNxTlvDictionary_SchemaVersion_V1, wireFormat); parcBuffer_Release(&wireFormat); // We have not set the message type or schema TransportMessage *tm = transportMessage_CreateFromDictionary(dictionary); transportMessage_SetInfo(tm, data->mock->connection, NULL); ccnxTlvDictionary_Release(&dictionary); // ------ // Now do the actual test of sending the transport message up the stack TransportMessage *test_tm = sendUp(data, tm); // It should now be parsed into an control message CCNxTlvDictionary *testdict = transportMessage_GetDictionary(test_tm); assertNotNull(testdict, "Failed to get dictionary from the transport message"); assertTrue(ccnxTlvDictionary_IsControl(testdict), "Dictionary says it is not a Control"); assertTrue(ccnxTlvDictionary_GetSchemaVersion(testdict) == CCNxTlvDictionary_SchemaVersion_V1, "Wrong schema, got %d expected %d", ccnxTlvDictionary_GetSchemaVersion(testdict), CCNxTlvDictionary_SchemaVersion_V1); transportMessage_Destroy(&tm); }
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); }
LONGBOW_TEST_CASE(Static, _ccnxWireFormatMessage_CreateWithImpl) { PARCBuffer *wireFormatV1 = parcBuffer_Wrap(v1_interest_nameA, sizeof(v1_interest_nameA), 0, sizeof(v1_interest_nameA)); CCNxWireFormatMessage *message = _ccnxWireFormatMessage_CreateWithImpl(&CCNxWireFormatFacadeV1_Implementation, wireFormatV1); assertNotNull(message, "Expected to create a V1 CCNxWireFormatMessage"); ccnxWireFormatMessage_Release(&message); parcBuffer_Release(&wireFormatV1); }
LONGBOW_TEST_CASE(Global, ccnxWireFormatMessage_Create) { PARCBuffer *wireFormat = parcBuffer_Wrap(v1_interest_nameA, sizeof(v1_interest_nameA), 0, sizeof(v1_interest_nameA)); CCNxWireFormatMessage *message = ccnxWireFormatMessage_Create(wireFormat); assertNotNull(message, "Got null CCNxWireFormatMessage, after attempting to create with buffer"); ccnxWireFormatMessage_Release(&message); parcBuffer_Release(&wireFormat); }
LONGBOW_TEST_CASE(Global, ccnxWireFormatMessage_WriteToFile) { const char string[] = "Hello dev null\n"; PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string)); CCNxWireFormatMessage *message = ccnxWireFormatMessage_FromInterestPacketType(CCNxTlvDictionary_SchemaVersion_V1, buffer); ccnxWireFormatMessage_WriteToFile(message, "/dev/null"); ccnxWireFormatMessage_Release(&message); parcBuffer_Release(&buffer); }
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, ccnxWireFormatMessage_SetProtectedRegionStart) { const char string[] = "Hello dev null\n"; PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string)); CCNxWireFormatMessage *message = ccnxWireFormatMessage_FromContentObjectPacketType(CCNxTlvDictionary_SchemaVersion_V1, buffer); size_t start = 5; bool success = ccnxWireFormatMessage_SetProtectedRegionStart(message, start); assertTrue(success, "Failed to put integer in to dictionary"); assertTrue(ccnxTlvDictionary_IsValueInteger(message, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedStart), "ProtectedStart not set"); ccnxWireFormatMessage_Release(&message); parcBuffer_Release(&buffer); }
LONGBOW_TEST_CASE(Global, metisMessage_CreateFromElasticBuffer) { char message_str[] = "\0x00Once upon a time, in a stack far away, a dangling pointer found its way to the top of the heap."; PARCBuffer *buff = parcBuffer_Wrap(message_str, sizeof(message_str), 0, sizeof(message_str)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromParcBuffer(buff, 1, 2, logger); metisLogger_Release(&logger); assertNotNull(message, "Got null from metisMessage_CreateFromBuffer"); assertTrue(message->ingressConnectionId == 1, "IngressConnectionId wrong, expected %d got %u", 1, message->ingressConnectionId); assertTrue(message->receiveTime == 2, "receiveTime wrong, expected %u got %" PRIu64, 2, message->receiveTime); metisMessage_Release(&message); parcBuffer_Release(&buff); }
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, ccnxWireFormatMessage_CreateContentObjectHash) { // >1234< const char string[] = "Hello dev null\n"; PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string)); CCNxWireFormatMessage *message = ccnxWireFormatMessage_FromContentObjectPacketType(CCNxTlvDictionary_SchemaVersion_V1, buffer); PARCCryptoHash *hash = ccnxWireFormatMessage_CreateContentObjectHash(message); ccnxWireFormatMessage_Release(&message); assertNull(hash, "Expect NULL for hash as it hasn't been encoded yet"); // We need to create a content object that is hashable CCNxName *name = ccnxName_CreateFromCString("lci:/test/content"); CCNxContentObject *contentObject = ccnxContentObject_CreateWithNameAndPayload(name, buffer); ccnxName_Release(&name); // This next stuff is to force an encode/decode to setup hash extents CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvPacket_DictionaryEncode(contentObject, NULL); ccnxContentObject_Release(&contentObject); PARCBuffer *encodedMessage = _iovecToParcBuffer(iovec); ccnxCodecNetworkBufferIoVec_Release(&iovec); // Decode message = ccnxWireFormatMessage_Create(encodedMessage); CCNxTlvDictionary *dictionary = ccnxWireFormatMessage_GetDictionary(message); bool success = ccnxCodecTlvPacket_BufferDecode(encodedMessage, dictionary); assertTrue(success, "Failed to decode buffer"); parcBuffer_Release(&encodedMessage); hash = ccnxWireFormatMessage_CreateContentObjectHash(message); // the correctness of the hash is tested in _ccnxWireFormatFacadeV1_ComputeHash assertNotNull(hash, "Got null hash from a good packet"); ccnxWireFormatMessage_Release(&message); parcCryptoHash_Release(&hash); parcBuffer_Release(&buffer); }
PARCBuffer * athenaTransportLinkModule_CreateMessageBuffer(CCNxMetaMessage *message) { PARCBuffer *buffer = ccnxWireFormatMessage_GetWireFormatBuffer(message); // If there is no PARCBuffer present, check for an IO vector and convert that into a contiguous buffer. if (buffer == NULL) { CCNxCodecNetworkBufferIoVec *iovec = ccnxWireFormatMessage_GetIoVec(message); if (iovec == NULL) { // if there's no iovec or buffer, encode the message and return the iovec athena_EncodeMessage(message); iovec = ccnxWireFormatMessage_GetIoVec(message); } assertNotNull(iovec, "Null io vector"); size_t iovcnt = ccnxCodecNetworkBufferIoVec_GetCount((CCNxCodecNetworkBufferIoVec *) iovec); const struct iovec *array = ccnxCodecNetworkBufferIoVec_GetArray((CCNxCodecNetworkBufferIoVec *) iovec); // If it's a single vector wrap it in a buffer to avoid a copy if (iovcnt == 1) { buffer = parcBuffer_Wrap(array[0].iov_base, array[0].iov_len, 0, array[0].iov_len); } else { size_t totalbytes = 0; for (int i = 0; i < iovcnt; i++) { totalbytes += array[i].iov_len; } buffer = parcBuffer_Allocate(totalbytes); for (int i = 0; i < iovcnt; i++) { parcBuffer_PutArray(buffer, array[i].iov_len, array[i].iov_base); } parcBuffer_Flip(buffer); } } else { buffer = parcBuffer_Acquire(buffer); } return buffer; }
PARCBuffer * parcBuffer_WrapCString(char *string) { size_t length = strlen(string); return parcBuffer_Wrap(string, length, 0, length); }
static int _UDPSend(AthenaTransportLink *athenaTransportLink, CCNxMetaMessage *ccnxMetaMessage) { struct _UDPLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink); if (ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage) == CCNxTlvDictionary_SchemaVersion_V0) { parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "sending deprecated version %d message\n", ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage)); } // Get a wire format buffer and write it out. PARCBuffer *wireFormatBuffer = ccnxWireFormatMessage_GetWireFormatBuffer(ccnxMetaMessage); if (wireFormatBuffer == NULL) { CCNxCodecNetworkBufferIoVec *iovec = ccnxWireFormatMessage_GetIoVec(ccnxMetaMessage); assertNotNull(iovec, "Null io vector"); size_t iovcnt = ccnxCodecNetworkBufferIoVec_GetCount((CCNxCodecNetworkBufferIoVec *) iovec); const struct iovec *array = ccnxCodecNetworkBufferIoVec_GetArray((CCNxCodecNetworkBufferIoVec *) iovec); // If it's a single vector wrap it in a buffer to avoid a copy if (iovcnt == 1) { wireFormatBuffer = parcBuffer_Wrap(array[0].iov_base, array[0].iov_len, 0, array[0].iov_len); } else { size_t totalbytes = 0; for (int i = 0; i < iovcnt; i++) { totalbytes += array[i].iov_len; } wireFormatBuffer = parcBuffer_Allocate(totalbytes); for (int i = 0; i < iovcnt; i++) { parcBuffer_PutArray(wireFormatBuffer, array[i].iov_len, array[i].iov_base); } parcBuffer_Flip(wireFormatBuffer); } } else { wireFormatBuffer = parcBuffer_Acquire(wireFormatBuffer); } size_t length = parcBuffer_Limit(wireFormatBuffer); char *buffer = parcBuffer_Overlay(wireFormatBuffer, length); if (linkData->link.mtu) { if (length > linkData->link.mtu) { errno = EMSGSIZE; parcBuffer_Release(&wireFormatBuffer); return -1; } } parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "sending message (size=%d)", length); ssize_t writeCount = 0; #ifdef LINUX_IGNORESIGPIPE writeCount = sendto(linkData->fd, buffer, length, MSG_NOSIGNAL, (struct sockaddr *) &linkData->link.peerAddress, linkData->link.peerAddressLength); #else writeCount = sendto(linkData->fd, buffer, length, 0, (struct sockaddr *) &linkData->link.peerAddress, linkData->link.peerAddressLength); #endif // on error close the link, else return to retry a zero write if (writeCount == -1) { if (errno == EPIPE) { athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Error); } parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "send error (%s)", strerror(errno)); parcBuffer_Release(&wireFormatBuffer); return -1; } // Short write if (writeCount != length) { linkData->_stats.receive_ShortWrite++; parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "short write"); parcBuffer_Release(&wireFormatBuffer); return -1; } parcBuffer_Release(&wireFormatBuffer); return 0; }