/** * Receive a ContentObject message that comes back from the tutorial_Server in response to an Interest we sent. * This message will be a chunk of the requested content, and should be received in ordered sequence. * Depending on the CCNxName in the content object, we hand it off to either _receiveFileChunk() or * _receiveDirectoryListingChunk() to process. * * @param [in] contentObject A CCNxContentObject containing a response to an CCNxInterest we sent. * @param [in] domainPrefix A CCNxName containing the domain prefix of the content we requested. * * @return The number of chunks of the content left to transfer. */ static uint64_t _receiveContentObject(CCNxContentObject *contentObject, const CCNxName *domainPrefix) { CCNxName *contentName = ccnxContentObject_GetName(contentObject); uint64_t chunkNumber = tutorialCommon_GetChunkNumberFromName(contentName); // Get the number of the final chunk, as specified by the sender. uint64_t finalChunkNumberSpecifiedByServer = ccnxContentObject_GetFinalChunkNumber(contentObject); // Get the type of the incoming message. Was it a response to a fetch' or a 'list' command? char *command = tutorialCommon_CreateCommandStringFromName(contentName, domainPrefix); // Process the payload. PARCBuffer *payload = ccnxContentObject_GetPayload(contentObject); if (strncasecmp(command, tutorialCommon_CommandList, strlen(command)) == 0) { // This is a chunk of the directory listing. _receiveDirectoryListingChunk(payload, chunkNumber, finalChunkNumberSpecifiedByServer); } else if (strncasecmp(command, tutorialCommon_CommandFetch, strlen(command)) == 0) { // This is a chunk of a file. char *fileName = tutorialCommon_CreateFileNameFromName(contentName); _receiveFileChunk(fileName, payload, chunkNumber, finalChunkNumberSpecifiedByServer); parcMemory_Deallocate((void **) &fileName); } else { printf("tutorial_Client: Unknown command: %s\n", command); } parcMemory_Deallocate((void **) &command); return (finalChunkNumberSpecifiedByServer - chunkNumber); // number of chunks left to transfer }
/** * 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; }