static void _processContentObject(Athena *athena, CCNxContentObject *contentObject, PARCBitVector *ingressVector) { // // * (1) If it does not match anything in the PIT, drop it // PARCBitVector *egressVector = athenaPIT_Match(athena->athenaPIT, contentObject, ingressVector); if (egressVector) { if (parcBitVector_NumberOfBitsSet(egressVector) > 0) { // // * (2) Add to the Content Store // athenaContentStore_PutContentObject(athena->athenaContentStore, contentObject); // // * (3) Reverse path forward it via PIT entries // const char *egressVectorString = parcBitVector_ToString(egressVector); parcLog_Debug(athena->log, "Content Object forwarded to %s.", egressVectorString); parcMemory_Deallocate(&egressVectorString); PARCBitVector *result = athenaTransportLinkAdapter_Send(athena->athenaTransportLinkAdapter, contentObject, egressVector); if (result) { // if there are failed channels, client will resend interest unless we wish to retry here parcBitVector_Release(&result); } } parcBitVector_Release(&egressVector); } }
LONGBOW_TEST_CASE(Global, parcBitVector_ToString) { PARCBitVector *parcBitVector = parcBitVector_Create(); assertTrue(parcBitVector, "parcBitVector_Create returned a NULL pointer"); char *string = parcBitVector_ToString(parcBitVector); assertTrue(strcmp(string, "[ ]") == 0, "parcBitVector_ToString returned unexpected representation (%s != [ ])", string); parcMemory_Deallocate(&string); parcBitVector_Set(parcBitVector, 10); parcBitVector_Set(parcBitVector, 1); string = parcBitVector_ToString(parcBitVector); assertTrue(strcmp(string, "[ 1 10 ]") == 0, "parcBitVector_ToString returned unexpected representation (%s != [ 1 10 ])", string); parcMemory_Deallocate(&string); parcBitVector_Release(&parcBitVector); }
static void _removeLink(void *context, PARCBitVector *linkVector) { Athena *athena = (Athena *) context; const char *linkVectorString = parcBitVector_ToString(linkVector); // cleanup specified links from the FIB and PIT, these calls are currently presumed synchronous bool result = athenaFIB_RemoveLink(athena->athenaFIB, linkVector); assertTrue(result, "Failed to remove link from FIB %s", linkVectorString); result = athenaPIT_RemoveLink(athena->athenaPIT, linkVector); assertTrue(result, "Failed to remove link from PIT %s", linkVectorString); parcMemory_Deallocate(&linkVectorString); }
LONGBOW_TEST_CASE(Global, athenaTransportLinkAdapter_SendReceive) { PARCURI *connectionURI; const char *result; CCNxMetaMessage *receiveMessage; PARCBitVector *resultVector; AthenaTransportLinkAdapter *athenaTransportLinkAdapter = athenaTransportLinkAdapter_Create(_removeLink, NULL); assertNotNull(athenaTransportLinkAdapter, "athenaTransportLinkAdapter_Create returned NULL"); _LoadModule(athenaTransportLinkAdapter, "TCP"); connectionURI = parcURI_Parse("tcp://127.0.0.1:50200/Listener/name=TCPListener"); result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, 0); assertNull(resultVector, "Received message when none sent"); connectionURI = parcURI_Parse("tcp://127.0.0.1:50200/name=TCP_1"); result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, 0); assertNull(resultVector, "Received message when none sent"); connectionURI = parcURI_Parse("tcp://127.0.0.1:50200/name=TCP_2"); result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, 0); assertNull(resultVector, "Received message when none sent"); connectionURI = parcURI_Parse("tcp://127.0.0.1:50200/name=TCP_3"); result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, 0); assertNull(resultVector, "Received message when none sent"); connectionURI = parcURI_Parse("tcp://127.0.0.1:50200/name=TCP_4"); result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, 0); assertNull(resultVector, "Received message when none sent"); connectionURI = parcURI_Parse("tcp://127.0.0.1:50200/name=TCP_5"); result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, 0); assertNull(resultVector, "Received message when none sent"); int closeResult = athenaTransportLinkAdapter_CloseByName(athenaTransportLinkAdapter, "TCP_3"); assertTrue(closeResult == 0, "athenaTransportLinkAdapter_CloseByName failed (%s)", strerror(errno)); connectionURI = parcURI_Parse("tcp://127.0.0.1:50200/name=TCP_3"); result = athenaTransportLinkAdapter_Open(athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, 0); assertNull(resultVector, "Received message when none sent"); CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar"); CCNxMetaMessage *sendMessage = ccnxInterest_CreateSimple(name); ccnxName_Release(&name); PARCBitVector *linkVector = parcBitVector_Create(); int linkId = athenaTransportLinkAdapter_LinkNameToId(athenaTransportLinkAdapter, "TCP_1"); parcBitVector_Set(linkVector, linkId); linkId = athenaTransportLinkAdapter_LinkNameToId(athenaTransportLinkAdapter, "TCP_2"); parcBitVector_Set(linkVector, linkId); linkId = athenaTransportLinkAdapter_LinkNameToId(athenaTransportLinkAdapter, "TCP_3"); parcBitVector_Set(linkVector, linkId); athena_EncodeMessage(sendMessage); resultVector = athenaTransportLinkAdapter_Send(athenaTransportLinkAdapter, sendMessage, linkVector); assertNull(resultVector, "athenaTransportLinkAdapter_Send failed"); usleep(1000); char *resultString; receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, -1); assertNotNull(resultVector, "athenaTransportLinkAdapter_Receive failed"); printf("Receive1 = %s\n", resultString = parcBitVector_ToString(resultVector)); assertTrue(parcBitVector_NumberOfBitsSet(resultVector) > 0, "athenaTransportLinkAdapter_Receive failed"); assertTrue(parcBitVector_NumberOfBitsSet(resultVector) == 1, "athenaTransportLinkAdapter_Receive returned message with more than one ingress link (%s)", resultString); parcMemory_Deallocate(&resultString); parcBitVector_Release(&resultVector); ccnxMetaMessage_Release(&receiveMessage); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, -1); assertNotNull(resultVector, "athenaTransportLinkAdapter_Receive failed"); printf("Receive2 = %s\n", resultString = parcBitVector_ToString(resultVector)); assertTrue(parcBitVector_NumberOfBitsSet(resultVector) > 0, "athenaTransportLinkAdapter_Receive failed"); assertTrue(parcBitVector_NumberOfBitsSet(resultVector) == 1, "athenaTransportLinkAdapter_Receive returned message with more than one ingress link (%s)", resultString); parcMemory_Deallocate(&resultString); parcBitVector_Release(&resultVector); ccnxMetaMessage_Release(&receiveMessage); receiveMessage = athenaTransportLinkAdapter_Receive(athenaTransportLinkAdapter, &resultVector, -1); assertNotNull(resultVector, "athenaTransportLinkAdapter_Receive failed"); printf("Receive3 = %s\n", resultString = parcBitVector_ToString(resultVector)); assertTrue(parcBitVector_NumberOfBitsSet(resultVector) > 0, "athenaTransportLinkAdapter_Receive failed"); assertTrue(parcBitVector_NumberOfBitsSet(resultVector) == 1, "athenaTransportLinkAdapter_Receive returned message with more than one ingress link (%s)", resultString); parcMemory_Deallocate(&resultString); parcBitVector_Release(&resultVector); ccnxMetaMessage_Release(&receiveMessage); closeResult = athenaTransportLinkAdapter_CloseByName(athenaTransportLinkAdapter, "TCP_1"); assertTrue(closeResult == 0, "athenaTransportLinkAdapter_CloseByName failed (%s)", strerror(errno)); closeResult = athenaTransportLinkAdapter_CloseByName(athenaTransportLinkAdapter, "TCP_2"); assertTrue(closeResult == 0, "athenaTransportLinkAdapter_CloseByName failed (%s)", strerror(errno)); resultVector = athenaTransportLinkAdapter_Send(athenaTransportLinkAdapter, sendMessage, linkVector); assertTrue(parcBitVector_NumberOfBitsSet(resultVector) == 2, "athenaTransportLinkAdapter_Send should have partially failed"); parcBitVector_Release(&linkVector); parcBitVector_Release(&resultVector); linkVector = parcBitVector_Create(); parcBitVector_Set(linkVector, 100); resultVector = athenaTransportLinkAdapter_Send(athenaTransportLinkAdapter, sendMessage, linkVector); assertTrue(parcBitVector_NumberOfBitsSet(resultVector) == 1, "athenaTransportLinkAdapter_Send should have failed to send to unknown link"); parcBitVector_Release(&resultVector); parcBitVector_Release(&linkVector); ccnxMetaMessage_Release(&sendMessage); athenaTransportLinkAdapter_Destroy(&athenaTransportLinkAdapter); }
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); } }