void metisConfiguration_Receive(MetisConfiguration *config, MetisMessage *message) { assertNotNull(config, "Parameter config must be non-null"); assertNotNull(message, "Parameter message must be non-null"); assertTrue(metisMessage_GetType(message) == MetisMessagePacketType_Control, "Message must be type CPI, expected %02x got %02x", MetisMessagePacketType_Control, metisMessage_GetType(message)); CCNxControl *control = metisMessage_CreateControlMessage(message); unsigned ingressId = metisMessage_GetIngressConnectionId(message); if (metisLogger_IsLoggable(config->logger, MetisLoggerFacility_Config, PARCLogLevel_Debug)) { char *str = parcJSON_ToCompactString(ccnxControl_GetJson(control)); metisLogger_Log(config->logger, MetisLoggerFacility_Config, PARCLogLevel_Debug, __func__, "%s received %s\n", __func__, str); parcMemory_Deallocate((void **) &str); } CCNxControl *response = _processControl(config, control, ingressId); metisConfiguration_SendResponse(config, response, ingressId); ccnxControl_Release(&response); ccnxControl_Release(&control); metisMessage_Release(&message); }
LONGBOW_TEST_CASE(Global, athena_ProcessControl_CPI_REGISTER_PREFIX) { PARCURI *connectionURI; Athena *athena = athena_Create(100); CCNxName *name = ccnxName_CreateFromCString("ccnx:/foo/bar"); CCNxControl *control = ccnxControl_CreateAddRouteToSelfRequest(name); // CPI_REGISTER_PREFIX CCNxMetaMessage *registerPrefixCommand = ccnxMetaMessage_CreateFromControl(control); ccnxControl_Release(&control); control = ccnxControl_CreateRemoveRouteToSelfRequest(name); // CPI_UNREGISTER_PREFIX CCNxMetaMessage *unregisterPrefixCommand = ccnxMetaMessage_CreateFromControl(control); ccnxControl_Release(&control); ccnxName_Release(&name); connectionURI = parcURI_Parse("tcp://localhost:50100/listener/name=TCPListener"); const char *result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); connectionURI = parcURI_Parse("tcp://localhost:50100/name=TCP_0"); result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI); assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno)); parcURI_Release(&connectionURI); int linkId = athenaTransportLinkAdapter_LinkNameToId(athena->athenaTransportLinkAdapter, "TCP_0"); PARCBitVector *ingressVector = parcBitVector_Create(); parcBitVector_Set(ingressVector, linkId); // Call _Receive() once to prime the link. Messages are dropped until _Receive() is called once. PARCBitVector *linksRead = NULL; CCNxMetaMessage *msg = athenaTransportLinkAdapter_Receive(athena->athenaTransportLinkAdapter, &linksRead, -1); assertNull(msg, "Expected to NOT receive a message after the first call to _Receive()"); CCNxMetaMessage *cpiMessages[2]; cpiMessages[0] = registerPrefixCommand; // CPI_REGISTER_PREFIX cpiMessages[1] = unregisterPrefixCommand; // CPI_UNREGISTER_PREFIX for (int i = 0; i < 2; i++) { CCNxMetaMessage *cpiMessageToSend = cpiMessages[i]; athena_ProcessMessage(athena, cpiMessageToSend, ingressVector); ccnxMetaMessage_Release(&cpiMessageToSend); CCNxMetaMessage *ack = athenaTransportLinkAdapter_Receive(athena->athenaTransportLinkAdapter, &linksRead, -1); assertNotNull(ack, "Expected a CPI_ACK message back"); assertTrue(ccnxMetaMessage_IsControl(ack), "Expected a control message back"); parcBitVector_Release(&linksRead); PARCJSON *json = ccnxControl_GetJson(ack); const PARCJSONValue *cpiAckResult = parcJSON_GetByPath(json, "CPI_ACK/REQUEST/RESULT"); bool commandResult = parcJSONValue_GetBoolean(cpiAckResult); assertTrue(commandResult, "Expected the ACK to contain RESULT=true"); ccnxMetaMessage_Release(&ack); } parcBitVector_Release(&ingressVector); athena_Release(&athena); }
static bool _ccnxPortalRTA_Ignore(void *privateData, const CCNxName *name, const CCNxStackTimeout *microSeconds) { CCNxControl *control = ccnxControl_CreateRemoveRouteToSelfRequest(name); CCNxMetaMessage *message = ccnxMetaMessage_CreateFromControl(control); ccnxControl_Release(&control); bool result = _ccnxPortalRTA_Send(privateData, message, CCNxStackTimeout_Never); // There is a problem here if the client invokes this function on a portal that is already receiving messages. // This simply absorbs messages until the receipt of the acknowledgement of this listen. // Perhaps what should happen is not read any messages and let the client sort it out in its read loop. if (result == true) { CCNxMetaMessage *response = _ccnxPortalRTA_Receive(privateData, microSeconds); if (response != NULL) { if (ccnxMetaMessage_IsControl(response)) { // TODO: Check that the response was success. result = true; } ccnxMetaMessage_Release(&response); } else { // We got a NULL reponse (possibly due to timeout). Since we always expect a // response from the forwarder, consider this a failure. result = false; } } ccnxMetaMessage_Release(&message); return result; }
/** * Called by the command parser for each command. * * The command parser will make a CCNxControl message inside the CCNxMetaMessage and send it here. * This function must return a ACK or NACK in a CCNxControl in a CCNxMetaMessage. * * @param [in] userdata A void * to MetisConfigurationFile * @param [in] msg The CCNxControl message to process * * @retval CCNxMetaMessage A CPI ACK or NACK in a CCNxControl in a CCNxMetaMessage * * Example: * @code * <#example#> * @endcode */ static CCNxMetaMessage * _writeRead(void *userdata, CCNxMetaMessage *msgin) { MetisConfigurationFile *configFile = (MetisConfigurationFile *) userdata; CCNxControl *request = ccnxMetaMessage_GetControl(msgin); CCNxControl *response = metisConfiguration_ReceiveControl(metisForwarder_GetConfiguration(configFile->metis), request, 0); CCNxMetaMessage *msgout = ccnxMetaMessage_CreateFromControl(response); ccnxControl_Release(&response); return msgout; }
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); }
LONGBOW_TEST_CASE(Global, cpiCancelFlow_CreateRequest) { const char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"CPI_CANCEL_FLOW\":{\"FLOW_NAME\":\"lci:/who/doesnt/like/pie\"}}}"; CCNxName *name = ccnxName_CreateFromURI("lci:/who/doesnt/like/pie"); PARCJSON *cpiRequest = cpiCancelFlow_CreateRequest(name); CCNxControl *controlRequest = ccnxControl_CreateCPIRequest(cpiRequest); PARCJSON *json = ccnxControl_GetJson(controlRequest); char buffer[1024]; sprintf(buffer, truth_format, cpi_GetSequenceNumber(controlRequest)); char *test_string = parcJSON_ToCompactString(json); assertTrue(strcmp(buffer, test_string) == 0, "Incorrect JSON, expected '%s' got '%s'", buffer, test_string); parcMemory_Deallocate((void **) &test_string); ccnxControl_Release(&controlRequest); parcJSON_Release(&cpiRequest); ccnxName_Release(&name); }
static CCNxControl * customWriteReadResponse(void *userdata, CCNxMetaMessage *messageToWrite) { CPIConnectionList *connlist = cpiConnectionList_Create(); CPIConnection *conn = cpiConnection_Create(1, cpiAddress_CreateFromInterface(1), cpiAddress_CreateFromInterface(2), cpiConnection_L2); cpiConnectionList_Append(connlist, conn); PARCJSON *connectionListAsJson = cpiConnectionList_ToJson(connlist); CCNxControl *inboundControlMessage = ccnxMetaMessage_GetControl(messageToWrite); // Create a response to the inbound Control message. CCNxControl *outboundControlMessage = cpi_CreateResponse(inboundControlMessage, connectionListAsJson); parcJSON_Release(&connectionListAsJson); ccnxControl_Release(&inboundControlMessage); cpiConnectionList_Destroy(&connlist); return outboundControlMessage; }