Exemple #1
0
void
athena_ProcessMessage(Athena *athena, CCNxMetaMessage *ccnxMessage, PARCBitVector *ingressVector)
{
    if (ccnxMetaMessage_IsInterest(ccnxMessage)) {
        const char *name = ccnxName_ToString(ccnxInterest_GetName(ccnxMessage));
        parcLog_Debug(athena->log, "Processing Interest Message: %s", name);
        parcMemory_Deallocate(&name);

        CCNxInterest *interest = ccnxMetaMessage_GetInterest(ccnxMessage);
        _processInterest(athena, interest, ingressVector);
        athena->stats.numProcessedInterests++;
    } else if (ccnxMetaMessage_IsContentObject(ccnxMessage)) {
        const char *name = ccnxName_ToString(ccnxContentObject_GetName(ccnxMessage));
        parcLog_Debug(athena->log, "Processing Content Object Message: %s", name);
        parcMemory_Deallocate(&name);

        CCNxContentObject *contentObject = ccnxMetaMessage_GetContentObject(ccnxMessage);
        _processContentObject(athena, contentObject, ingressVector);
        athena->stats.numProcessedContentObjects++;
    } else if (ccnxMetaMessage_IsControl(ccnxMessage)) {
        parcLog_Debug(athena->log, "Processing Control Message");

        CCNxControl *control = ccnxMetaMessage_GetControl(ccnxMessage);
        _processControl(athena, control, ingressVector);
        athena->stats.numProcessedControlMessages++;
    } else if (ccnxMetaMessage_IsInterestReturn(ccnxMessage)) {
        parcLog_Debug(athena->log, "Processing Interest Return Message");

        CCNxInterestReturn *interestReturn = ccnxMetaMessage_GetInterestReturn(ccnxMessage);
        _processInterestReturn(athena, interestReturn, ingressVector);
        athena->stats.numProcessedInterestReturns++;
    } else {
        trapUnexpectedState("Invalid CCNxMetaMessage type");
    }
}
PARCJSON *
ccnxManifest_ToJSON(const CCNxManifest *manifest)
{
    PARCJSON *root = parcJSON_Create();

    char *nameString = ccnxName_ToString(ccnxManifest_GetName(manifest));
    parcJSON_AddString(root, "locator", nameString);
    parcMemory_Deallocate(&nameString);

    PARCJSONArray *array = parcJSONArray_Create();
    for (size_t i = 0; i < ccnxManifest_GetNumberOfHashGroups(manifest); i++) {
        CCNxManifestHashGroup *group = ccnxManifest_GetHashGroupByIndex(manifest, i);
        PARCJSON *groupJson = ccnxManifestHashGroup_ToJson(group);
        PARCJSONValue *jsonValue = parcJSONValue_CreateFromJSON(groupJson);

        parcJSONArray_AddValue(array, jsonValue);

        parcJSONValue_Release(&jsonValue);
        parcJSON_Release(&groupJson);
        ccnxManifestHashGroup_Release(&group);
    }
    parcJSON_AddArray(root, "HashGroups", array);
    parcJSONArray_Release(&array);

    return root;
}
PARCBuffer *
makePayload(const CCNxName *interestName, const char *commandString)
{
    char *commandToExecute;

    char *nameAsString = ccnxName_ToString(interestName);
    int failure = asprintf(&commandToExecute, commandString, nameAsString);
    assertTrue(failure > -1, "Error asprintf");
    parcMemory_Deallocate((void **) &nameAsString);

    PARCBufferComposer *accumulator = parcBufferComposer_Create();

    FILE *fp = popen(commandToExecute, "r");
    if (fp != NULL) {
        unsigned char buffer[1024];

        while (feof(fp) == 0) {
            size_t length = fread(buffer, sizeof(char), sizeof(buffer), fp);
            parcBufferComposer_PutArray(accumulator, buffer, length);
        }
        pclose(fp);
    } else {
        parcBufferComposer_PutString(accumulator, "Cannot execute: ");
        parcBufferComposer_PutString(accumulator, commandString);
    }

    PARCBuffer *payload = parcBufferComposer_ProduceBuffer(accumulator);
    parcBufferComposer_Release(&accumulator);

    return payload;
}
/**
 * Given a CCnxInterest that matched our domain prefix, see what the embedded command is and
 * create a corresponding CCNxContentObject as a response. The resulting CCNxContentObject
 * must eventually be released by calling ccnxContentObject_Release().
 *
 * @param [in] interest A CCNxInterest that matched the specified domain prefix.
 * @param [in] domainPrefix A CCNxName containing the domain prefix.
 * @param [in] directoryPath A string containing the path to the directory being served.
 *
 * @return A newly creatd CCNxContentObject contaning a response to the specified Interest,
 *         or NULL if the Interest couldn't be answered.
 */
static CCNxContentObject *
_createInterestResponse(const CCNxInterest *interest, const CCNxName *domainPrefix, const char *directoryPath)
{
    CCNxName *interestName = ccnxInterest_GetName(interest);

    char *command = tutorialCommon_CreateCommandStringFromName(interestName, domainPrefix);

    uint64_t requestedChunkNumber = tutorialCommon_GetChunkNumberFromName(interestName);

    char *interestNameString = ccnxName_ToString(interestName);
    printf("tutorialServer: received Interest for chunk %d of %s, command = %s\n",
           (int) requestedChunkNumber, interestNameString, command);
    parcMemory_Deallocate((void **) &interestNameString);

    CCNxContentObject *result = NULL;
    if (strncasecmp(command, tutorialCommon_CommandList, strlen(command)) == 0) {
        // This was a 'list' command. We should return the requested chunk of the directory listing.
        result = _createListResponse(interestName, directoryPath, requestedChunkNumber);
    } else if (strncasecmp(command, tutorialCommon_CommandFetch, strlen(command)) == 0) {
        // This was a 'fetch' command. We should return the requested chunk of the file specified.
        char *fileName = tutorialCommon_CreateFileNameFromName(interestName);
        result = _createFetchResponse(interestName, directoryPath, fileName, requestedChunkNumber);
        parcMemory_Deallocate((void **) &fileName);
    }

    parcMemory_Deallocate((void **) &command);

    return result;
}
Exemple #5
0
static void
_athenaLRUContentStoreEntry_Display(const _AthenaLRUContentStoreEntry *entry, int indentation)
{
    int childIndentation = indentation + 2; //strlen("AthenaLRUContentStoreEntry");
    parcDisplayIndented_PrintLine(indentation,
                                  "AthenaLRUContentStoreEntry {%p, prev = %p, next = %p, co = %p, size = %zu",
                                  entry, entry->prev, entry->next,
                                  entry->contentObject, entry->sizeInBytes);
    const CCNxName *name = ccnxContentObject_GetName(entry->contentObject);
    if (name) {
        char *nameString = ccnxName_ToString(name);
        parcDisplayIndented_PrintLine(childIndentation, "Name: %p [%s]", name, nameString);
        parcMemory_Deallocate(&nameString);
    } else {
        parcDisplayIndented_PrintLine(childIndentation, "Name: NULL");
    }
    if (entry->hasExpiryTime) {
        parcDisplayIndented_PrintLine(childIndentation, "ExpiryTime: [%"
                                      PRIu64
                                      "]", entry->expiryTime);
    }

    if (entry->hasRecommendedCacheTime) {
        parcDisplayIndented_PrintLine(childIndentation, "RecommendedCacheTime: [%"
                                      PRIu64
                                      "]", entry->recommendedCacheTime);
    }

    parcDisplayIndented_PrintLine(childIndentation, "}");
}
PARCJSON *
ccnxManifestHashGroup_ToJson(const CCNxManifestHashGroup *group)
{
    PARCJSON *root = parcJSON_Create();

    PARCJSONArray *ptrList = parcJSONArray_Create();
    for (size_t i = 0; i < parcLinkedList_Size(group->pointers); i++) {
        CCNxManifestHashGroupPointer *ptr = (CCNxManifestHashGroupPointer *) parcLinkedList_GetAtIndex(group->pointers, i);
        PARCJSON *ptrJson = parcJSON_Create();

        // Type.
        parcJSON_AddInteger(ptrJson, "type", ccnxManifestHashGroupPointer_GetType(ptr));

        // Digest.
        char *digestString = parcBuffer_ToHexString(ptr->digest);
        parcJSON_AddString(ptrJson, "digest", digestString);
        parcMemory_Deallocate(&digestString);

        // Add the tuple to the list.
        PARCJSONValue *val = parcJSONValue_CreateFromJSON(ptrJson);
        parcJSONArray_AddValue(ptrList, val);

        // Cleanup
        parcJSONValue_Release(&val);
        parcJSON_Release(&ptrJson);
    }
    root = parcJSON_AddArray(root, "HashGroup", ptrList);
    parcJSONArray_Release(&ptrList);

    if (group->overallDataDigest != NULL) {
        char *digestString = parcBuffer_ToHexString(group->overallDataDigest);
        root = parcJSON_AddString(root, "overallDataDigest", digestString);
        parcMemory_Deallocate((void **) &digestString);
    }

    if (group->locator != NULL) {
        char *locatorString = ccnxName_ToString(group->locator);
        root = parcJSON_AddString(root, "locator", locatorString);
        parcMemory_Deallocate((void **) &locatorString);
    }

    if (group->entrySize > 0) {
        root = parcJSON_AddInteger(root, "entrySize", group->entrySize);
    }

    if (group->dataSize > 0) {
        root = parcJSON_AddInteger(root, "dataSize", group->dataSize);
    }

    if (group->blockSize > 0) {
        root = parcJSON_AddInteger(root, "blockSize", group->blockSize);
    }

    if (group->treeHeight > 0) {
        root = parcJSON_AddInteger(root, "treeHeight", group->treeHeight);
    }

    return root;
}
LONGBOW_TEST_CASE(Global, cpiCancelFlow_NameFromControlMessage)
{
    CCNxName *name = ccnxName_CreateFromURI("lci:/who/doesnt/like/pie");
    PARCJSON *cpiRequest = cpiCancelFlow_CreateRequest(name);
    CCNxControl *controlRequest = ccnxControl_CreateCPIRequest(cpiRequest);

    CCNxName *test_name = cpiCancelFlow_NameFromControlMessage(controlRequest);
    assertTrue(ccnxName_Equals(test_name, name),
               "Expected %s actual %s",
               ccnxName_ToString(name),
               ccnxName_ToString(test_name));

    ccnxName_Release(&test_name);
    ccnxControl_Release(&controlRequest);
    parcJSON_Release(&cpiRequest);
    ccnxName_Release(&name);
}
int
ccnServe(const PARCIdentity *identity, const CCNxName *listenName, const char *commandString)
{
    parcSecurity_Init();

    CCNxPortalFactory *factory = ccnxPortalFactory_Create(identity);

    CCNxPortal *portal = ccnxPortalFactory_CreatePortal(factory, ccnxPortalRTA_Message);
    assertNotNull(portal, "Expected a non-null CCNxPortal pointer.");

    if (ccnxPortal_Listen(portal, listenName, 365 * 86400, CCNxStackTimeout_Never)) {
        while (true) {
            CCNxMetaMessage *request = ccnxPortal_Receive(portal, CCNxStackTimeout_Never);

            if (request == NULL) {
                break;
            }

            CCNxInterest *interest = ccnxMetaMessage_GetInterest(request);

            if (interest != NULL) {
                CCNxName *interestName = ccnxInterest_GetName(interest);

                PARCBuffer *payload = makePayload(interestName, commandString);

                CCNxContentObject *contentObject = ccnxContentObject_CreateWithDataPayload(interestName, payload);

                CCNxMetaMessage *message = ccnxMetaMessage_CreateFromContentObject(contentObject);
                if (ccnxPortal_Send(portal, message, CCNxStackTimeout_Never) == false) {
                    fprintf(stderr, "ccnxPortal_Write failed: %d\n", ccnxPortal_GetError(portal));
                }
                {
                    char *name = ccnxName_ToString(interestName);
                    time_t theTime = time(0);
                    char *time = ctime(&theTime);
                    printf("%24.24s  %s\n", time, name);
                    parcMemory_Deallocate((void **) &name);
                }

                parcBuffer_Release(&payload);
            }
            ccnxMetaMessage_Release(&request);
        }
    }

    ccnxPortal_Release(&portal);

    ccnxPortalFactory_Release(&factory);

    parcSecurity_Fini();

    return 0;
}
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;
}
void
ccnxPortalAnchor_Display(const CCNxPortalAnchor *anchor, int indentation)
{
    char *prefix = ccnxName_ToString(anchor->prefix);

    parcDisplayIndented_PrintLine(indentation, "CCNxPortalAnchor@%p {", anchor);
    parcDisplayIndented_PrintLine(indentation+1, ".prefix=%s}", prefix);
    parcDisplayIndented_PrintLine(indentation+1, ".expireTime=%ld", anchor->expireTime);

    /* Call Display() functions for the fields here. */
    parcDisplayIndented_PrintLine(indentation, "}");
    parcMemory_Deallocate(&prefix);
}
static size_t
_calculateSizeOfContentObject(const CCNxContentObject *contentObject)
{
    size_t result = 0;
    char *nameAsString = ccnxName_ToString(ccnxContentObject_GetName(contentObject));
    result += strlen(nameAsString);
    parcMemory_DeallocateImpl((void **) &nameAsString);

    PARCBuffer *payload = ccnxContentObject_GetPayload(contentObject);
    if (payload != NULL) {
        result += parcBuffer_Limit(payload);
    }
    return result;
}
PARCBufferComposer *
ccnxPortalAnchor_BuildString(const CCNxPortalAnchor *anchor, PARCBufferComposer *composer)
{
    char *name = ccnxName_ToString(anchor->prefix);

    char expireTime[64];
    if (anchor->expireTime == -1) {
        strcpy(expireTime, "                      never");
    } else {
        parcTime_TimeAsRFC3339(anchor->expireTime, expireTime);
    }
    parcBufferComposer_Format(composer, "{ %s %s }", name, expireTime);

    parcMemory_Deallocate(&name);

    return composer;
}
PARCJSON *
ccnxPortalAnchor_ToJSON(const CCNxPortalAnchor *anchor)
{
    ccnxPortalAnchor_OptionalAssertValid(anchor);

    PARCJSON *result = parcJSON_Create();
    if (result != NULL) {
        char *prefix = ccnxName_ToString(anchor->prefix);

        parcJSON_AddString(result, "namePrefix", prefix);
        parcJSON_AddInteger(result, "expireTime", (int64_t) anchor->expireTime);

        parcMemory_Deallocate(&prefix);
    }

    return result;
}
Exemple #14
0
void
athenaInterestControl_LogConfigurationChange(Athena *athena, CCNxName *ccnxName, const char *format, ...)
{
    if (athena->configurationLog) {
        if (ccnxName) {
            const char *name = ccnxName_ToString(ccnxName);
            parcOutputStream_WriteCString(athena->configurationLog, name);
            parcMemory_Deallocate(&name);
        }

        char configurationLogBuffer[MAXPATHLEN] = {0};
        if (format) {
            va_list ap;
            va_start(ap, format);

            parcOutputStream_WriteCString(athena->configurationLog, " ");
            vsprintf(configurationLogBuffer, format, ap);
            parcOutputStream_WriteCString(athena->configurationLog, configurationLogBuffer);
        }
        parcOutputStream_WriteCString(athena->configurationLog, "\n");
    }
}
Exemple #15
0
static CCNxMetaMessage *
_FIB_Command(Athena *athena, CCNxInterest *interest, PARCBitVector *ingress)
{
    CCNxMetaMessage *responseMessage;
    responseMessage = athenaFIB_ProcessMessage(athena->athenaFIB, interest);
    if (responseMessage) {
        return responseMessage;
    }

    CCNxName *ccnxName = ccnxInterest_GetName(interest);
    if (ccnxName_GetSegmentCount(ccnxName) > AthenaCommandSegment) {
        CCNxNameSegment *nameSegment = ccnxName_GetSegment(ccnxName, AthenaCommandSegment);
        char *command = ccnxNameSegment_ToString(nameSegment);

        if ((strcasecmp(command, AthenaCommand_Add) == 0) || (strcasecmp(command, AthenaCommand_Remove) == 0)) {
            char *arguments = _get_arguments(interest);

            if (arguments == NULL) {
                responseMessage = _create_response(athena, ccnxName, "No link or prefix arguments given to %s route command", command);
                parcMemory_Deallocate(&command);
                return responseMessage;
            }

            char linkName[MAXPATHLEN];
            char prefix[MAXPATHLEN];
            PARCBitVector *linkVector;

            // {Add,Remove} Route arguments "<prefix> [<linkName>]", if linkName not specified, use the incoming link id ([de-]registration)
            int numberOfArguments = sscanf(arguments, "%s %s", prefix, linkName);
            if (numberOfArguments == 2) {
                int linkId = athenaTransportLinkAdapter_LinkNameToId(athena->athenaTransportLinkAdapter, linkName);
                if (linkId == -1) {
                    responseMessage = _create_response(athena, ccnxName, "Unknown linkName %s", linkName);
                    parcMemory_Deallocate(&command);
                    parcMemory_Deallocate(&arguments);
                    return responseMessage;
                }
                linkVector = parcBitVector_Create();
                parcBitVector_Set(linkVector, linkId);
            } else if (numberOfArguments == 1) { // use ingress link
                linkVector = parcBitVector_Acquire(ingress);
            } else {
                responseMessage = _create_response(athena, ccnxName, "No prefix specified or too many arguments");
                parcMemory_Deallocate(&command);
                parcMemory_Deallocate(&arguments);
                return responseMessage;
            }

            CCNxName *prefixName = ccnxName_CreateFromCString(prefix);
            if (prefixName == NULL) {
                responseMessage = _create_response(athena, ccnxName, "Unable to parse prefix %s", prefix);
                parcMemory_Deallocate(&command);
                parcMemory_Deallocate(&arguments);
                parcBitVector_Release(&linkVector);
                return responseMessage;
            }

            int result = false;
            if (strcasecmp(command, AthenaCommand_Add) == 0) {
                result = athenaFIB_AddRoute(athena->athenaFIB, prefixName, linkVector);
            } else if (strcasecmp(command, AthenaCommand_Remove) == 0) {
                result = athenaFIB_DeleteRoute(athena->athenaFIB, prefixName, linkVector);
            }

            if (result == true) {
                char *routePrefix = ccnxName_ToString(prefixName);
                const char *linkIdName = athenaTransportLinkAdapter_LinkIdToName(athena->athenaTransportLinkAdapter, parcBitVector_NextBitSet(linkVector, 0));
                responseMessage = _create_response(athena, ccnxName, "%s route %s -> %s", command, routePrefix, linkIdName);
                athenaInterestControl_LogConfigurationChange(athena, ccnxName, "%s %s", routePrefix, linkIdName);
                parcMemory_Deallocate(&routePrefix);
            } else {
                responseMessage = _create_response(athena, ccnxName, "%s failed", command);
            }
            parcBitVector_Release(&linkVector);
            ccnxName_Release(&prefixName);

            parcMemory_Deallocate(&arguments);
        } else if (strcasecmp(command, AthenaCommand_List) == 0) {
            // Need to create the response here because as the FIB doesn't know the linkName
            parcLog_Debug(athena->log, "FIB List command invoked");
            PARCList *fibEntries = athenaFIB_CreateEntryList(athena->athenaFIB);
            responseMessage = _create_FIBList_response(athena, ccnxName, fibEntries);
            parcList_Release(&fibEntries);
        } else {
            responseMessage = _create_response(athena, ccnxName, "Unknown command: %s", command);
        }

        parcMemory_Deallocate(&command);
    }
    return responseMessage;
}
Exemple #16
0
static CCNxMetaMessage *
_create_FIBList_response(Athena *athena, CCNxName *ccnxName, PARCList *fibEntryList)
{
    PARCJSON *jsonPayload = parcJSON_Create();
    PARCJSONArray *jsonEntryList = parcJSONArray_Create();
    parcJSON_AddArray(jsonPayload, JSON_KEY_RESULT, jsonEntryList);

    for (size_t i = 0; i < parcList_Size(fibEntryList); ++i) {
        AthenaFIBListEntry *entry = parcList_GetAtIndex(fibEntryList, i);
        if (entry != NULL) {
            CCNxName *prefixName = athenaFIBListEntry_GetName(entry);
            if (prefixName) {
                char *prefix = ccnxName_ToString(prefixName);
                int linkId = athenaFIBListEntry_GetLinkId(entry);
                const char *linkName = athenaTransportLinkAdapter_LinkIdToName(athena->athenaTransportLinkAdapter, linkId);
                parcLog_Debug(athena->log, "  Route: %s->%s", prefix, linkName);

                PARCJSON *jsonItem = parcJSON_Create();
                parcJSON_AddString(jsonItem, JSON_KEY_NAME, prefix);
                parcJSON_AddString(jsonItem, JSON_KEY_LINK, linkName);

                PARCJSONValue *jsonItemValue = parcJSONValue_CreateFromJSON(jsonItem);
                parcJSON_Release(&jsonItem);

                parcJSONArray_AddValue(jsonEntryList, jsonItemValue);
                parcJSONValue_Release(&jsonItemValue);

                parcMemory_Deallocate(&prefix);
            } else {
                int linkId = athenaFIBListEntry_GetLinkId(entry);
                const char *linkName = athenaTransportLinkAdapter_LinkIdToName(athena->athenaTransportLinkAdapter, linkId);
                parcLog_Debug(athena->log, "  Route: <empty>->%s", linkName);

                PARCJSON *jsonItem = parcJSON_Create();
                parcJSON_AddString(jsonItem, JSON_KEY_NAME, "");
                parcJSON_AddString(jsonItem, JSON_KEY_LINK, linkName);

                PARCJSONValue *jsonItemValue = parcJSONValue_CreateFromJSON(jsonItem);
                parcJSON_Release(&jsonItem);

                parcJSONArray_AddValue(jsonEntryList, jsonItemValue);
                parcJSONValue_Release(&jsonItemValue);
            }
        }
    }

    char *jsonString = parcJSON_ToString(jsonPayload);

    parcJSONArray_Release(&jsonEntryList);
    parcJSON_Release(&jsonPayload);

    PARCBuffer *payload = parcBuffer_CreateFromArray(jsonString, strlen(jsonString));

    CCNxContentObject *contentObject =
        ccnxContentObject_CreateWithNameAndPayload(ccnxName, parcBuffer_Flip(payload));

    struct timeval tv;
    gettimeofday(&tv, NULL);
    uint64_t nowInMillis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
    ccnxContentObject_SetExpiryTime(contentObject, nowInMillis + 100); // this response is good for 100 millis

    CCNxMetaMessage *result = ccnxMetaMessage_CreateFromContentObject(contentObject);

    ccnxContentObject_Release(&contentObject);
    parcBuffer_Release(&payload);
    parcMemory_Deallocate(&jsonString);

    athena_EncodeMessage(result);
    return result;
}
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);
}
Exemple #18
0
static void
_processInterest(Athena *athena, CCNxInterest *interest, PARCBitVector *ingressVector)
{
    uint8_t hoplimit;

    //
    // *   (0) Hoplimit check, exclusively on interest messages
    //
    int linkId = parcBitVector_NextBitSet(ingressVector, 0);
    if (athenaTransportLinkAdapter_IsNotLocal(athena->athenaTransportLinkAdapter, linkId)) {
        hoplimit = ccnxInterest_GetHopLimit(interest);
        if (hoplimit == 0) {
            // We should never receive a message with a hoplimit of 0 from a non-local source.
            parcLog_Error(athena->log,
                          "Received a message with a hoplimit of zero from a non-local source (%s).",
                          athenaTransportLinkAdapter_LinkIdToName(athena->athenaTransportLinkAdapter, linkId));
            return;
        }
        ccnxInterest_SetHopLimit(interest, hoplimit - 1);
    }

    //
    // *   (1) if the interest is in the ContentStore, reply and return,
    //     assuming that other PIT entries were satisified when the content arrived.
    //
    CCNxMetaMessage *content = athenaContentStore_GetMatch(athena->athenaContentStore, interest);
    if (content) {
        const char *ingressVectorString = parcBitVector_ToString(ingressVector);
        parcLog_Debug(athena->log, "Forwarding content from store to %s", ingressVectorString);
        parcMemory_Deallocate(&ingressVectorString);
        PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, content, ingressVector);
        if (result) { // failed channels - client will resend interest unless we wish to optimize things here
            parcBitVector_Release(&result);
        }
        return;
    }

    //
    // *   (2) add it to the PIT, if it was aggregated or there was an error we're done, otherwise we
    //         forward the interest.  The expectedReturnVector is populated with information we get from
    //         the FIB and used to verify content objects ingress ports when they arrive.
    //
    PARCBitVector *expectedReturnVector;
    AthenaPITResolution result;
    if ((result = athenaPIT_AddInterest(athena->athenaPIT, interest, ingressVector, &expectedReturnVector)) != AthenaPITResolution_Forward) {
        if (result == AthenaPITResolution_Error) {
            parcLog_Error(athena->log, "PIT resolution error");
        }
        return;
    }

    // Divert interests destined to the forwarder, we assume these are control messages
    CCNxName *ccnxName = ccnxInterest_GetName(interest);
    if (ccnxName_StartsWith(ccnxName, athena->athenaName) == true) {
        _processInterestControl(athena, interest, ingressVector);
        return;
    }

    //
    // *   (3) if it's in the FIB, forward, then update the PIT expectedReturnVector so we can verify
    //         when the returned object arrives that it came from an interface it was expected from.
    //         Interest messages with a hoplimit of 0 will never be sent out by the link adapter to a
    //         non-local interface so we need not check that here.
    //
    ccnxName = ccnxInterest_GetName(interest);
    PARCBitVector *egressVector = athenaFIB_Lookup(athena->athenaFIB, ccnxName);

    if (egressVector != NULL) {
        // Remove the link the interest came from if it was included in the FIB entry
        parcBitVector_ClearVector(egressVector, ingressVector);
        // If no links remain, send a no route interest return message
        if (parcBitVector_NumberOfBitsSet(egressVector) == 0) {
            CCNxInterestReturn *interestReturn = ccnxInterestReturn_Create(interest, CCNxInterestReturn_ReturnCode_NoRoute);
            PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, interestReturn, ingressVector);
            parcBitVector_Release(&result);
            ccnxInterestReturn_Release(&interestReturn);
        } else {
            parcBitVector_SetVector(expectedReturnVector, egressVector);
            PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, interest, egressVector);
            if (result) { // remove failed channels - client will resend interest unless we wish to optimize here
                parcBitVector_ClearVector(expectedReturnVector, result);
                parcBitVector_Release(&result);
            }
        }
    } else {
        // No FIB entry found, return a NoRoute interest return and remove the entry from the PIT.
        CCNxInterestReturn *interestReturn = ccnxInterestReturn_Create(interest, CCNxInterestReturn_ReturnCode_NoRoute);
        PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, interestReturn, ingressVector);
        parcBitVector_Release(&result);
        ccnxInterestReturn_Release(&interestReturn);
        const char *name = ccnxName_ToString(ccnxName);
        if (athenaPIT_RemoveInterest(athena->athenaPIT, interest, ingressVector) != true) {
            parcLog_Error(athena->log, "Unable to remove interest (%s) from the PIT.", name);
        }
        parcLog_Debug(athena->log, "Name (%s) not found in FIB and no default route. Message dropped.", name);
        parcMemory_Deallocate(&name);
    }
}