/** * Listen for arriving Interests and respond to them if possible. We expect that the Portal we are passed is * listening for messages matching the specified domainPrefix. * * @param [in] portal The CCNxPortal that we will read from. * @param [in] domainPrefix A CCNxName containing the domain prefix that the specified `portal` is listening for. * @param [in] directoryPath A string containing the path to the directory being served. * * @return true if at least one Interest is received and responded to, false otherwise. */ static bool _receiveAndAnswerInterests(CCNxPortal *portal, const CCNxName *domainPrefix, const char *directoryPath) { bool result = false; CCNxMetaMessage *inboundMessage = NULL; while ((inboundMessage = ccnxPortal_Receive(portal)) != NULL) { if (ccnxMetaMessage_IsInterest(inboundMessage)) { CCNxInterest *interest = ccnxMetaMessage_GetInterest(inboundMessage); CCNxContentObject *response = _createInterestResponse(interest, domainPrefix, directoryPath); // At this point, response has either the requested chunk of the request file/command, // or remains NULL. if (response != NULL) { // We had a response, so send it back through the Portal. CCNxMetaMessage *responseMessage = ccnxMetaMessage_CreateFromContentObject(response); if (ccnxPortal_Send(portal, responseMessage) == false) { fprintf(stderr, "ccnxPortal_Send failed (error %d). Is the Forwarder running?\n", ccnxPortal_GetError(portal)); } ccnxMetaMessage_Release(&responseMessage); ccnxContentObject_Release(&response); result = true; // We have received, and responded to, at least one Interest. } } ccnxMetaMessage_Release(&inboundMessage); } return result; }
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"); } }
int reader_writer(CCNxPortalFactory *factory, const char *uri) { CCNxPortal *portal = ccnxPortalFactory_GetInstance(factory, ccnxPortalTypeDatagram, ccnxPortalProtocol_TLV, &ccnxPortalAttributes_Blocking); CCNxName *prefix = ccnxName_CreateFromURI(uri); CCNxName *bye = ccnxName_CreateFromURI("lci:/Hello/Goodbye%21"); CCNxName *contentname = ccnxName_CreateFromURI("lci:/Hello/World"); if (ccnxPortal_Listen(portal, prefix, 365 * 86400, CCNxStackTimeout_Never)) { CCNxMetaMessage *msg; while ((msg = ccnxPortal_Receive(portal, CCNxStackTimeout_Never)) != NULL) { if (ccnxMetaMessage_IsInterest(msg)) { CCNxInterest *interest = ccnxMetaMessage_GetInterest(msg); CCNxName *interestName = ccnxInterest_GetName(interest); if (ccnxName_Equals(interestName, contentname)) { const PARCKeyId *publisherKeyId = ccnxPortal_GetKeyId(portal); char buffer[128]; time_t theTime = time(0); sprintf(buffer, "Hello World. The time is %s", ctime(&theTime)); PARCBuffer *payload = parcBuffer_CreateFromArray(buffer, 128); parcBuffer_Flip(payload); PARCBuffer *b = parcBuffer_Acquire(payload); CCNxContentObject *uob = ccnxContentObject_CreateWithDataPayload(contentname, b); // missing NULL check, case 1024 CCNxMetaMessage *message = ccnxMetaMessage_CreateFromContentObject(uob); if (ccnxPortal_Send(portal, message, CCNxTransportStackTimeCCNxStackTimeout_Neverout_Never) == false) { fprintf(stderr, "ccnx_write failed\n"); } // ccnxMessage_Release(message); } else if (ccnxName_Equals(interestName, bye)) { break; } } else { ccnxMetaMessage_Display(msg, 0); } ccnxMetaMessage_Release(&msg); } } ccnxName_Release(&prefix); ccnxName_Release(&bye); ccnxName_Release(&contentname); ccnxPortal_Release(&portal); return 0; }
PARCBitVector * athenaTransportLinkAdapter_Send(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, CCNxMetaMessage *ccnxMetaMessage, PARCBitVector *linkOutputVector) { PARCBitVector *resultVector = parcBitVector_Create(); int nextLinkToWrite = 0; if (athenaTransportLinkAdapter->instanceList == NULL) { return resultVector; } while ((nextLinkToWrite = parcBitVector_NextBitSet(linkOutputVector, nextLinkToWrite)) >= 0) { athenaTransportLinkAdapter->stats.messageSend_Attempted++; if (nextLinkToWrite >= parcArrayList_Size(athenaTransportLinkAdapter->instanceList)) { athenaTransportLinkAdapter->stats.messageSend_LinkDoesNotExist++; nextLinkToWrite++; continue; } AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, nextLinkToWrite); if (athenaTransportLink == NULL) { athenaTransportLinkAdapter->stats.messageSend_LinkDoesNotExist++; nextLinkToWrite++; continue; } if (!(athenaTransportLink_GetEvent(athenaTransportLink) & AthenaTransportLinkEvent_Send)) { athenaTransportLinkAdapter->stats.messageSend_LinkNotAcceptingSendRequests++; nextLinkToWrite++; continue; } // If we're sending an interest to a non-local link, // check that it has a sufficient hoplimit. if (ccnxMetaMessage_IsInterest(ccnxMetaMessage)) { if (athenaTransportLink_IsNotLocal(athenaTransportLink)) { if (ccnxInterest_GetHopLimit(ccnxMetaMessage) == 0) { athenaTransportLinkAdapter->stats.messageSend_HopLimitExceeded++; nextLinkToWrite++; continue; } } } int result = athenaTransportLink_Send(athenaTransportLink, ccnxMetaMessage); if (result == 0) { athenaTransportLinkAdapter->stats.messageSent++; parcBitVector_Set(resultVector, nextLinkToWrite); } else { athenaTransportLinkAdapter->stats.messageSend_LinkSendFailed++; } nextLinkToWrite++; } return resultVector; }
LONGBOW_TEST_CASE(Global, ccnxMetaMessage_IsInterest) { CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar"); CCNxInterest *interest = ccnxInterest_CreateSimple(name); CCNxMetaMessage *portalMessage = ccnxMetaMessage_CreateFromInterest(interest); assertTrue(ccnxMetaMessage_IsInterest(portalMessage), "Expected portal message to be an Interest"); assertFalse(ccnxMetaMessage_IsContentObject(portalMessage), "Did not expect portal message to be a ContentObject"); assertFalse(ccnxMetaMessage_IsControl(portalMessage), "Did not expect portal message to be a Control message"); ccnxMetaMessage_Release(&portalMessage); ccnxInterest_Release(&interest); ccnxName_Release(&name); }
static CCNxMetaMessage * _athenaLRUContentStore_ProcessMessage(AthenaContentStoreImplementation *store, const CCNxMetaMessage *message) { CCNxMetaMessage *result = NULL; AthenaLRUContentStore *impl = (AthenaLRUContentStore *) store; if (ccnxMetaMessage_IsInterest(message)) { CCNxInterest *interest = ccnxMetaMessage_GetInterest(message); CCNxName *queryName = ccnxInterest_GetName(interest); uint64_t chunkNumber = 0; bool hasChunkNumber = false; _getChunkNumberFromName(queryName, &chunkNumber, &hasChunkNumber); assertFalse(hasChunkNumber, "LRUContentStore queries don't yet support more than 1 chunk."); PARCBuffer *responsePayload = NULL; // Find the arguments to our query. size_t argSegmentIndex = 0; if (_getSegmentIndexOfQueryArgs(queryName, AthenaModule_ContentStore, &argSegmentIndex)) { CCNxNameSegment *queryTypeSegment = ccnxName_GetSegment(queryName, argSegmentIndex); char *queryTypeString = ccnxNameSegment_ToString(queryTypeSegment); // e.g. "stat" char *statString = "stat"; if (strncasecmp(queryTypeString, statString, strlen(statString)) == 0) { responsePayload = _processStatQuery(impl, queryName, argSegmentIndex + 1, chunkNumber); } parcMemory_Deallocate(&queryTypeString); } if (responsePayload != NULL) { CCNxContentObject *contentObjectResponse = ccnxContentObject_CreateWithNameAndPayload( ccnxInterest_GetName(interest), responsePayload); result = ccnxMetaMessage_CreateFromContentObject(contentObjectResponse); ccnxContentObject_SetExpiryTime(contentObjectResponse, parcClock_GetTime(impl->wallClock) + 100); // this response is good for 100 millis ccnxContentObject_Release(&contentObjectResponse); parcBuffer_Release(&responsePayload); } } return result; // could be NULL }
LONGBOW_TEST_CASE(Global, ccnxMetaMessage_IsContentObject) { CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar"); PARCBuffer *payload = parcBuffer_WrapCString("This is some data. It's not good data, but it is data."); CCNxContentObject *contentObject = ccnxContentObject_CreateWithNameAndPayload(name, payload); CCNxMetaMessage *portalMessage = ccnxMetaMessage_CreateFromContentObject(contentObject); assertTrue(ccnxMetaMessage_IsContentObject(portalMessage), "Expected portal message to be an ContentObject"); assertFalse(ccnxMetaMessage_IsInterest(portalMessage), "Did not expect portal message to be an Interest"); assertFalse(ccnxMetaMessage_IsControl(portalMessage), "Did not expect portal message to be a Control message"); ccnxMetaMessage_Release(&portalMessage); ccnxContentObject_Release(&contentObject); parcBuffer_Release(&payload); ccnxName_Release(&name); }