/** * Create and return a CCNxInterest whose Name contains our commend (e.g. "fetch" or "list"), * and, optionally, the name of a target object (e.g. "file.txt"). The newly created CCNxInterest * must eventually be released by calling ccnxInterest_Release(). * * @param command The command to embed in the created CCNxInterest. * @param targetName The name of the content, if any, that the command applies to. * * @return A newly created CCNxInterest for the specified command and targetName. */ static CCNxInterest * _createInterest(const char *command, const char *targetName) { CCNxName *interestName = ccnxName_CreateFromURI(tutorialCommon_DomainPrefix); // Start with the prefix. We append to this. // Create a NameSegment for our command, which we will append after the prefix we just created. PARCBuffer *commandBuffer = parcBuffer_WrapCString((char *) command); CCNxNameSegment *commandSegment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, commandBuffer); parcBuffer_Release(&commandBuffer); // Append the new command segment to the prefix ccnxName_Append(interestName, commandSegment); ccnxNameSegment_Release(&commandSegment); // If we have a target, then create another NameSegment for it and append that. if (targetName != NULL) { // Create a NameSegment for our target object PARCBuffer *targetBuf = parcBuffer_WrapCString((char *) targetName); CCNxNameSegment *targetSegment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_NAME, targetBuf); parcBuffer_Release(&targetBuf); // Append it to the ccnxName. ccnxName_Append(interestName, targetSegment); ccnxNameSegment_Release(&targetSegment); } CCNxInterest *result = ccnxInterest_CreateSimple(interestName); ccnxName_Release(&interestName); return result; }
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(Global, ccnxNameSegmentNumber_Create8bits) { uint64_t expected = 0x12; CCNxNameSegment *segment = ccnxNameSegmentNumber_Create(CCNxNameLabelType_CHUNK, expected); uint64_t actual = ccnxNameSegmentNumber_Value(segment); assertTrue(expected == actual, "Expected 0x%" PRIX64 " actual 0x%" PRIX64 "", expected, actual); ccnxNameSegment_Release(&segment); }
LONGBOW_TEST_CASE(Global, athena_ProcessContentObject) { PARCURI *connectionURI; Athena *athena = athena_Create(100); CCNxName *name = ccnxName_CreateFromCString("lci:/cakes/and/pies"); uint64_t chunkNum = 0; CCNxNameSegment *chunkSegment = ccnxNameSegmentNumber_Create(CCNxNameLabelType_CHUNK, chunkNum); ccnxName_Append(name, chunkSegment); ccnxNameSegment_Release(&chunkSegment); PARCBuffer *payload = parcBuffer_WrapCString("this is a payload"); CCNxContentObject *contentObject = ccnxContentObject_CreateWithNameAndPayload(name, payload); ccnxName_Release(&name); parcBuffer_Release(&payload); connectionURI = parcURI_Parse("tcp://localhost:50100/listener/name=TCPListener"); const char *result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); connectionURI = parcURI_Parse("tcp://localhost:50100/name=TCP_0"); result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); int linkId = athenaTransportLinkAdapter_LinkNameToId(athena->athenaTransportLinkAdapter, "TCP_0"); PARCBitVector *ingressVector = parcBitVector_Create(); parcBitVector_Set(ingressVector, linkId); athena_EncodeMessage(contentObject); athena_ProcessMessage(athena, contentObject, ingressVector); parcBitVector_Release(&ingressVector); // Make sure we recover processing a "nameless" content object payload = parcBuffer_WrapCString("Hello World"); CCNxContentObject *reply = ccnxContentObject_CreateWithPayload(payload); parcBuffer_Release(&payload); CCNxMetaMessage *response = ccnxMetaMessage_CreateFromContentObject(reply); ccnxContentObject_Release(&reply); athena_EncodeMessage(response); athena_ProcessMessage(athena, response, ingressVector); assertNull(ingressVector, "Processing nameless content object didn't fail."); ccnxInterest_Release(&contentObject); ccnxInterest_Release(&response); athena_Release(&athena); }
/** * Create a CCNxContentObject with the given LCI name, chunknumber, and payload. */ static CCNxContentObject * _createContentObject(char *lci, uint64_t chunkNum, PARCBuffer *payload) { CCNxName *name = ccnxName_CreateFromURI(lci); CCNxNameSegment *chunkSegment = ccnxNameSegmentNumber_Create(CCNxNameLabelType_CHUNK, chunkNum); ccnxName_Append(name, chunkSegment); CCNxContentObject *result = ccnxContentObject_CreateWithDataPayload(name, payload); ccnxName_Release(&name); ccnxNameSegment_Release(&chunkSegment); return result; }
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, athena_ProcessInterest) { PARCURI *connectionURI; Athena *athena = athena_Create(100); CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar/baz"); CCNxInterest *interest = ccnxInterest_CreateSimple(name); uint64_t chunkNum = 0; CCNxNameSegment *chunkSegment = ccnxNameSegmentNumber_Create(CCNxNameLabelType_CHUNK, chunkNum); ccnxName_Append(name, chunkSegment); ccnxNameSegment_Release(&chunkSegment); PARCBuffer *payload = parcBuffer_WrapCString("this is a payload"); CCNxContentObject *contentObject = ccnxContentObject_CreateWithNameAndPayload(name, payload); parcBuffer_Release(&payload); struct timeval tv; gettimeofday(&tv, NULL); uint64_t nowInMillis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); ccnxContentObject_SetExpiryTime(contentObject, nowInMillis + 100000); // expire in 100 seconds connectionURI = parcURI_Parse("tcp://localhost:50100/listener/name=TCPListener"); const char *result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed(%s)", strerror(errno)); parcURI_Release(&connectionURI); connectionURI = parcURI_Parse("tcp://localhost:50100/name=TCP_0/local=false"); result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); connectionURI = parcURI_Parse("tcp://localhost:50100/name=TCP_1/local=false"); result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); int linkId = athenaTransportLinkAdapter_LinkNameToId(athena->athenaTransportLinkAdapter, "TCP_0"); PARCBitVector *interestIngressVector = parcBitVector_Create(); parcBitVector_Set(interestIngressVector, linkId); linkId = athenaTransportLinkAdapter_LinkNameToId(athena->athenaTransportLinkAdapter, "TCP_1"); PARCBitVector *contentObjectIngressVector = parcBitVector_Create(); parcBitVector_Set(contentObjectIngressVector, linkId); athena_EncodeMessage(interest); athena_EncodeMessage(contentObject); // Before FIB entry interest should not be forwarded athena_ProcessMessage(athena, interest, interestIngressVector); // Add route for interest, it should now be forwarded athenaFIB_AddRoute(athena->athenaFIB, name, contentObjectIngressVector); CCNxName *defaultName = ccnxName_CreateFromCString("lci:/"); athenaFIB_AddRoute(athena->athenaFIB, defaultName, contentObjectIngressVector); ccnxName_Release(&defaultName); // Process exact interest match athena_ProcessMessage(athena, interest, interestIngressVector); // Process a super-interest match CCNxName *superName = ccnxName_CreateFromCString("lci:/foo/bar/baz/unmatched"); CCNxInterest *superInterest = ccnxInterest_CreateSimple(superName); athena_EncodeMessage(superInterest); athena_ProcessMessage(athena, superInterest, interestIngressVector); ccnxName_Release(&superName); ccnxInterest_Release(&superInterest); // Process no-match/default route interest CCNxName *noMatchName = ccnxName_CreateFromCString("lci:/buggs/bunny"); CCNxInterest *noMatchInterest = ccnxInterest_CreateSimple(noMatchName); athena_EncodeMessage(noMatchInterest); athena_ProcessMessage(athena, noMatchInterest, interestIngressVector); ccnxName_Release(&noMatchName); ccnxInterest_Release(&noMatchInterest); // Create a matching content object that the store should retain and reply to the following interest with athena_ProcessMessage(athena, contentObject, contentObjectIngressVector); athena_ProcessMessage(athena, interest, interestIngressVector); parcBitVector_Release(&interestIngressVector); parcBitVector_Release(&contentObjectIngressVector); ccnxName_Release(&name); ccnxInterest_Release(&interest); ccnxInterest_Release(&contentObject); athena_Release(&athena); }
static void _destroy(CCNxInterestPayloadId **idP) { CCNxInterestPayloadId *id = *idP; ccnxNameSegment_Release(&id->nameSegment); }