/** * Given a command (e.g "fetch") and an optional target name (e.g. "file.txt"), create an appropriate CCNxInterest * and write it to the Portal. * * @param command The command to be handled. * @param targetName The name of the target content, if any, that the command applies to. * * @return true If a CCNxInterest for the specified command and optional target was successfully issued and answered. */ static bool _executeUserCommand(const char *command, const char *targetName) { bool result = false; CCNxPortalFactory *factory = _setupConsumerPortalFactory(); CCNxPortal *portal = ccnxPortalFactory_CreatePortal(factory, ccnxPortalRTA_Chunked); assertNotNull(portal, "Expected a non-null CCNxPortal pointer."); // Given the user's command and optional target, create an Interest. CCNxInterest *interest = _createInterest(command, targetName); // Send the Interest through the Portal, and wait for a response. CCNxMetaMessage *message = ccnxMetaMessage_CreateFromInterest(interest); if (ccnxPortal_Send(portal, message, CCNxStackTimeout_Never)) { CCNxName *domainPrefix = ccnxName_CreateFromURI(tutorialCommon_DomainPrefix); // e.g. 'lci:/ccnx/tutorial' result = _receiveResponseToIssuedInterest(portal, domainPrefix); ccnxName_Release(&domainPrefix); } ccnxMetaMessage_Release(&message); ccnxInterest_Release(&interest); ccnxPortal_Release(&portal); ccnxPortalFactory_Release(&factory); return result; }
/** * Run the consumer to fetch the specified file. Save it to disk once transferred. * * @param [in] target Name of the content to request. * @param [in] outFile Name of the file to which the buffer will be written. */ static int _ccnxFileRepoClient_Run(char *target, char *outFile) { parcSecurity_Init(); PARCLog *log = _ccnxFileRepoClient_CreateLogger(); CCNxPortalFactory *factory = _setupConsumerPortalFactory(); CCNxPortal *portal = ccnxPortalFactory_CreatePortal(factory, ccnxPortalRTA_Message); assertNotNull(portal, "Expected a non-null CCNxPortal pointer."); CCNxName *name = ccnxName_CreateFromCString(target); CCNxInterest *interest = ccnxInterest_CreateSimple(name); CCNxMetaMessage *message = ccnxMetaMessage_CreateFromInterest(interest); if (ccnxPortal_Send(portal, message, CCNxStackTimeout_Never)) { while (ccnxPortal_IsError(portal) == false) { CCNxMetaMessage *response = ccnxPortal_Receive(portal, CCNxStackTimeout_Never); if (response != NULL) { if (ccnxMetaMessage_IsManifest(response)) { parcLog_Info(log, "Received root manifest. Beginning to retrieve the content."); // Extract the manifest and instantiate a new fetcher for it CCNxManifest *root = ccnxMetaMessage_GetManifest(response); CCNxFileRepoManifestFetcher *fetcher = ccnxFileRepoManifestFetcher_Create(portal, root); // Initialize the file offset and I/O buffer size_t fileOffset = 0; PARCBuffer *chunkBuffer = parcBuffer_Allocate(ccnxFileRepoCommon_ClientBufferSize); // Start reading from the manifest until done bool done = false; while (!done) { // Reset the buffer information parcBuffer_SetPosition(chunkBuffer, 0); parcBuffer_SetLimit(chunkBuffer, ccnxFileRepoCommon_ClientBufferSize); // Fill the buffer with data from the manifest done = ccnxFileRepoManifestFetcher_FillBuffer(fetcher, chunkBuffer); parcBuffer_Flip(chunkBuffer); // Write the buffer to the file size_t totalSize = parcBuffer_Remaining(chunkBuffer); _ccnxFileRepoClient_AppendBufferToFile(outFile, chunkBuffer, fileOffset); fileOffset += totalSize; // Flip the buffer back around for writing parcBuffer_Flip(chunkBuffer); } parcBuffer_Release(&chunkBuffer); break; } else if (ccnxMetaMessage_IsContentObject(response)) { parcLog_Info(log, "Received a content object. Dump the payload and exit."); CCNxContentObject *contentObject = ccnxMetaMessage_GetContentObject(response); PARCBuffer *payload = ccnxContentObject_GetPayload(contentObject); _ccnxFileRepoClient_AppendBufferToFile(outFile, payload, 0); break; } } ccnxMetaMessage_Release(&response); } } ccnxPortal_Release(&portal); ccnxPortalFactory_Release(&factory); parcSecurity_Fini(); return 0; }