MetisGenericEther * metisGenericEther_Create(MetisForwarder *metis, const char *deviceName, uint16_t etherType) { assertNotNull(metis, "Parameter metis must be non-null"); // The Darwin generic ether allows a NULL device name, it is used in the unit tests. MetisGenericEther *ether = NULL; if (metisEthernet_IsValidEthertype(etherType)) { ether = parcObject_CreateInstance(MetisGenericEther); ether->ethertype = etherType; ether->logger = metisLogger_Acquire(metisForwarder_GetLogger(metis)); ether->etherSocket = -1; // invalid valid ether->workBuffer = parcEventBuffer_Create(); ether->macAddress = NULL; ether->mtu = metisSystem_InterfaceMtu(metis, deviceName); _darwinEthernet_SetInterfaceAddress(ether, deviceName); bool success = _darwinEthernet_SetupReceive(ether, deviceName); if (success) { if (metisLogger_IsLoggable(ether->logger, MetisLoggerFacility_IO, PARCLogLevel_Info)) { char *str = parcBuffer_ToHexString(ether->macAddress); metisLogger_Log(ether->logger, MetisLoggerFacility_IO, PARCLogLevel_Info, __func__, "GenericEther %p created on device %s (%s) for ethertype 0x%04x fd %d bufferLength %u mtu %u", (void *) ether, deviceName, str, etherType, ether->etherSocket, ether->etherBufferLength, ether->mtu); parcMemory_Deallocate((void **) &str); } } else { if (metisLogger_IsLoggable(ether->logger, MetisLoggerFacility_IO, PARCLogLevel_Error)) { metisLogger_Log(ether->logger, MetisLoggerFacility_IO, PARCLogLevel_Error, __func__, "GenericEther failed to created on device %s for ethertype 0x%04x", deviceName, etherType); } // this will also null ether metisGenericEther_Release(ðer); } assertTrue(ether->etherBufferLength < 65536, "Buffer length way too big, expected less than 65536 got %u", ether->etherBufferLength); } else { if (metisLogger_IsLoggable(metisForwarder_GetLogger(metis), MetisLoggerFacility_IO, PARCLogLevel_Error)) { metisLogger_Log(metisForwarder_GetLogger(metis), MetisLoggerFacility_IO, PARCLogLevel_Error, __func__, "GenericEther failed to created on device %s for ethertype 0x%04x, invalid ethertype", deviceName, etherType); } } return ether; }
MetisPIT * metisStandardPIT_Create(MetisForwarder *metis) { assertNotNull(metis, "Parameter must be non-null"); size_t allocation = sizeof(MetisPIT) + sizeof(MetisStandardPIT); MetisPIT *generic = parcMemory_AllocateAndClear(allocation); assertNotNull(generic, "parcMemory_AllocateAndClear(%zu) returned NULL", allocation); generic->closure = (uint8_t *) generic + sizeof(MetisPIT); MetisStandardPIT *pit = metisPIT_Closure(generic); pit->metis = metis; pit->logger = metisLogger_Acquire(metisForwarder_GetLogger(metis)); pit->table = metisMatchingRulesTable_Create(_metisPIT_PitEntryDestroyer); if (metisLogger_IsLoggable(pit->logger, MetisLoggerFacility_Processor, PARCLogLevel_Debug)) { metisLogger_Log(pit->logger, MetisLoggerFacility_Processor, PARCLogLevel_Debug, __func__, "PIT %p created", (void *) pit); } generic->getPitEntry = _metisStandardPIT_GetPitEntry; generic->receiveInterest = _metisStandardPIT_ReceiveInterest; generic->release = _metisStandardPIT_Destroy; generic->removeInterest = _metisStandardPIT_RemoveInterest; generic->satisfyInterest = _metisStandardPIT_SatisfyInterest; return generic; }
MetisConfigurationFile * metisConfigurationFile_Create(MetisForwarder *metis, const char *filename) { assertNotNull(metis, "Parameter metis must be non-null"); assertNotNull(filename, "Parameter filename must be non-null"); MetisConfigurationFile *configFile = parcObject_CreateInstance(MetisConfigurationFile); if (configFile) { configFile->linesRead = 0; configFile->metis = metis; configFile->filename = parcMemory_StringDuplicate(filename, strlen(filename)); assertNotNull(configFile->filename, "Could not copy string '%s'", filename); // setup the control state for the command parser configFile->controlState = metisControlState_Create(configFile, _writeRead); // we do not register Help commands metisControlState_RegisterCommand(configFile->controlState, metisControlRoot_Create(configFile->controlState)); // open the file and make sure we can read it configFile->fh = fopen(configFile->filename, "r"); if (configFile->fh) { if (metisLogger_IsLoggable(metisForwarder_GetLogger(metis), MetisLoggerFacility_Config, PARCLogLevel_Debug)) { metisLogger_Log(metisForwarder_GetLogger(metis), MetisLoggerFacility_Config, PARCLogLevel_Debug, __func__, "Open config file %s", configFile->filename); } } else { if (metisLogger_IsLoggable(metisForwarder_GetLogger(metis), MetisLoggerFacility_Config, PARCLogLevel_Error)) { metisLogger_Log(metisForwarder_GetLogger(metis), MetisLoggerFacility_Config, PARCLogLevel_Error, __func__, "Could not open config file %s: (%d) %s", configFile->filename, errno, strerror(errno)); } // failure cleanup the object -- this nulls it so final return null be NULL metisConfigurationFile_Release(&configFile); } } return configFile; }
MetisConfiguration * metisConfiguration_Create(MetisForwarder *metis) { assertNotNull(metis, "Parameter metis must be non-null"); MetisConfiguration *config = parcMemory_AllocateAndClear(sizeof(MetisConfiguration)); assertNotNull(config, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisConfiguration)); config->metis = metis; config->logger = metisLogger_Acquire(metisForwarder_GetLogger(metis)); config->cli = NULL; config->maximumContentObjectStoreSize = 100000; config->symbolicNameTable = metisSymbolicNameTable_Create(); return config; }
MetisIoOperations * metisStreamConnection_OpenConnection(MetisForwarder *metis, MetisAddressPair *pair, bool isLocal) { assertNotNull(metis, "Parameter metis must be non-null"); assertNotNull(pair, "Parameter pair must be non-null"); // if there's an error on the bind or connect, will return NULL PARCEventQueue *bufferEventVector = metisDispatcher_StreamBufferConnect(metisForwarder_GetDispatcher(metis), pair); if (bufferEventVector == NULL) { // error opening connection return NULL; } _MetisStreamState *stream = parcMemory_AllocateAndClear(sizeof(_MetisStreamState)); assertNotNull(stream, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(_MetisStreamState)); stream->metis = metis; stream->logger = metisLogger_Acquire(metisForwarder_GetLogger(metis)); stream->fd = parcEventQueue_GetFileDescriptor(bufferEventVector); stream->bufferEventVector = bufferEventVector; stream->id = metisForwarder_GetNextConnectionId(metis); stream->addressPair = pair; stream->isClosed = false; // allocate a connection MetisIoOperations *io_ops = parcMemory_AllocateAndClear(sizeof(MetisIoOperations)); assertNotNull(io_ops, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisIoOperations)); memcpy(io_ops, &_template, sizeof(MetisIoOperations)); io_ops->closure = stream; parcEventQueue_SetCallbacks(stream->bufferEventVector, _conn_readcb, NULL, _conn_eventcb, (void *) io_ops); parcEventQueue_Enable(stream->bufferEventVector, PARCEventType_Read); // we start in DOWN state, until remote side answers metisMessenger_Send(metisForwarder_GetMessenger(stream->metis), metisMissive_Create(MetisMissiveType_ConnectionCreate, stream->id)); _setConnectionState(stream, false); if (metisLogger_IsLoggable(stream->logger, MetisLoggerFacility_IO, PARCLogLevel_Info)) { char *pair_str = metisAddressPair_ToString(pair); metisLogger_Log(stream->logger, MetisLoggerFacility_IO, PARCLogLevel_Info, __func__, "StreamConnection %p connect for address pair %s", (void *) stream, pair_str); free(pair_str); } return io_ops; }
MetisIoOperations * metisStreamConnection_AcceptConnection(MetisForwarder *metis, int fd, MetisAddressPair *pair, bool isLocal) { _MetisStreamState *stream = parcMemory_AllocateAndClear(sizeof(_MetisStreamState)); assertNotNull(stream, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(_MetisStreamState)); MetisDispatcher *dispatcher = metisForwarder_GetDispatcher(metis); PARCEventScheduler *eventBase = metisDispatcher_GetEventScheduler(dispatcher); stream->bufferEventVector = parcEventQueue_Create(eventBase, fd, PARCEventQueueOption_CloseOnFree | PARCEventQueueOption_DeferCallbacks); stream->metis = metis; stream->logger = metisLogger_Acquire(metisForwarder_GetLogger(metis)); stream->fd = fd; stream->id = metisForwarder_GetNextConnectionId(metis); stream->addressPair = pair; stream->isClosed = false; // allocate a connection MetisIoOperations *io_ops = parcMemory_AllocateAndClear(sizeof(MetisIoOperations)); assertNotNull(io_ops, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisIoOperations)); memcpy(io_ops, &_template, sizeof(MetisIoOperations)); io_ops->closure = stream; parcEventQueue_SetCallbacks(stream->bufferEventVector, _conn_readcb, NULL, _conn_eventcb, (void *) io_ops); parcEventQueue_Enable(stream->bufferEventVector, PARCEventType_Read); metisMessenger_Send(metisForwarder_GetMessenger(stream->metis), metisMissive_Create(MetisMissiveType_ConnectionCreate, stream->id)); // As we are acceting a connection, we begin in the UP state _setConnectionState(stream, true); if (metisLogger_IsLoggable(stream->logger, MetisLoggerFacility_IO, PARCLogLevel_Debug)) { char *pair_str = metisAddressPair_ToString(pair); metisLogger_Log(stream->logger, MetisLoggerFacility_IO, PARCLogLevel_Debug, __func__, "StreamConnection %p accept for address pair %s", (void *) stream, pair_str); free(pair_str); } return io_ops; }
bool metisConfigurationFile_Process(MetisConfigurationFile *configFile) { assertNotNull(configFile, "Parameter configFile must be non-null"); // default to a "true" return value and only set to false if we encounter an error. bool success = true; #define BUFFERLEN 2048 char buffer[BUFFERLEN]; configFile->linesRead = 0; // always clear errors and fseek to start of file in case we get called multiple times. clearerr(configFile->fh); rewind(configFile->fh); while (success && fgets(buffer, BUFFERLEN, configFile->fh) != NULL) { configFile->linesRead++; char *stripedBuffer = _trim(buffer); if (strlen(stripedBuffer) > 0) { if (stripedBuffer[0] != '#') { // not empty and not a comment // _parseArgs will modify the string char *copy = parcMemory_StringDuplicate(stripedBuffer, strlen(stripedBuffer)); PARCList *args = _parseArgs(copy); MetisCommandReturn result = metisControlState_DispatchCommand(configFile->controlState, args); // we ignore EXIT from the configuration file if (result == MetisCommandReturn_Failure) { if (metisLogger_IsLoggable(metisForwarder_GetLogger(configFile->metis), MetisLoggerFacility_Config, PARCLogLevel_Error)) { metisLogger_Log(metisForwarder_GetLogger(configFile->metis), MetisLoggerFacility_Config, PARCLogLevel_Error, __func__, "Error on input file %s line %d: %s", configFile->filename, configFile->linesRead, stripedBuffer); } success = false; } parcList_Release(&args); parcMemory_Deallocate((void **) ©); } } } if (ferror(configFile->fh)) { if (metisLogger_IsLoggable(metisForwarder_GetLogger(configFile->metis), MetisLoggerFacility_Config, PARCLogLevel_Error)) { metisLogger_Log(metisForwarder_GetLogger(configFile->metis), MetisLoggerFacility_Config, PARCLogLevel_Error, __func__, "Error on input file %s line %d: (%d) %s", configFile->filename, configFile->linesRead, errno, strerror(errno)); } success = false; } return success; }
static void metisConfiguration_SendResponse(MetisConfiguration *config, CCNxControl *response, unsigned egressId) { PARCBuffer *responseBuffer = metisTlv_EncodeControlPlaneInformation(response); MetisMessage *tlvEncodedResponse = metisMessage_CreateFromParcBuffer(responseBuffer, 0, metisForwarder_GetTicks(config->metis), metisForwarder_GetLogger(config->metis)); parcBuffer_Release(&responseBuffer); MetisConnectionTable *connectionTable = metisForwarder_GetConnectionTable(config->metis); const MetisConnection *conn = metisConnectionTable_FindById(connectionTable, egressId); assertNotNull(conn, "Got null connection for control message we just received"); metisConnection_Send(conn, tlvEncodedResponse); metisMessage_Release(&tlvEncodedResponse); }