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; }
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; }
MetisDispatcher * metisDispatcher_Create(MetisLogger *logger) { MetisDispatcher *dispatcher = parcMemory_AllocateAndClear(sizeof(MetisDispatcher)); assertNotNull(dispatcher, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisDispatcher)); dispatcher->Base = parcEventScheduler_Create(); dispatcher->logger = metisLogger_Acquire(logger); assertNotNull(dispatcher->Base, "Got NULL from parcEventScheduler_Create()"); return dispatcher; }
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; }
MetisHopByHopFragmenter * metisHopByHopFragmenter_Create(MetisLogger *logger, unsigned mtu) { MetisHopByHopFragmenter *fragmenter = parcMemory_Allocate(sizeof(MetisHopByHopFragmenter)); if (fragmenter) { fragmenter->nextReceiveFragSequenceNumber = 0; fragmenter->nextSendFragSequenceNumber = 0; fragmenter->logger = metisLogger_Acquire(logger); fragmenter->mtu = mtu; fragmenter->receiveQueueCapacity = 128; // this is a many-to-one queue, so not too big fragmenter->sendQueueCapacity = 2048; // this is a one-to-many queue, so bigger (e.g. 64 KB in to 1KB payloads) fragmenter->receiveQueue = parcRingBuffer1x1_Create(fragmenter->receiveQueueCapacity, _ringBufferDestroyer); fragmenter->sendQueue = parcRingBuffer1x1_Create(fragmenter->sendQueueCapacity, _ringBufferDestroyer); fragmenter->currentReceiveBuffer = parcEventBuffer_Create(); fragmenter->parserState = _ParserState_Idle; } return fragmenter; }
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; }
static bool _metisLRUContentStore_Init(_MetisLRUContentStore *store, MetisContentStoreConfig *config, MetisLogger *logger) { bool result = false; store->logger = metisLogger_Acquire(logger); size_t initialSize = config->objectCapacity * 2; memset(&store->stats, 0, sizeof(_MetisLRUContentStoreStats)); store->objectCapacity = config->objectCapacity; store->objectCount = 0; // initial size must be at least 1 or else the data structures break. initialSize = (initialSize == 0) ? 1 : initialSize; store->indexByExpirationTime = metisTimeOrderedList_Create((MetisTimeOrderList_KeyCompare *) metisContentStoreEntry_CompareExpiryTime); store->indexByRecommendedCacheTime = metisTimeOrderedList_Create((MetisTimeOrderList_KeyCompare *) metisContentStoreEntry_CompareRecommendedCacheTime); store->indexByNameHash = parcHashCodeTable_Create_Size(metisHashTableFunction_MessageNameEquals, metisHashTableFunction_MessageNameHashCode, NULL, NULL, initialSize); store->indexByNameAndKeyIdHash = parcHashCodeTable_Create_Size(metisHashTableFunction_MessageNameAndKeyIdEquals, metisHashTableFunction_MessageNameAndKeyIdHashCode, NULL, NULL, initialSize); store->storageByNameAndObjectHashHash = parcHashCodeTable_Create_Size(metisHashTableFunction_MessageNameAndObjectHashEquals, metisHashTableFunction_MessageNameAndObjectHashHashCode, NULL, _hashTableFunction_ContentStoreEntryDestroyer, initialSize); store->lru = metisLruList_Create(); // If any of the index tables couldn't be allocated, we can't continue. if ((store->indexByExpirationTime == NULL) || (store->indexByNameAndKeyIdHash == NULL) || (store->indexByNameHash == NULL) || (store->indexByRecommendedCacheTime == NULL) || (store->storageByNameAndObjectHashHash == NULL) || (store->lru == NULL)) { if (metisLogger_IsLoggable(store->logger, MetisLoggerFacility_Processor, PARCLogLevel_Error)) { metisLogger_Log(store->logger, MetisLoggerFacility_Processor, PARCLogLevel_Error, __func__, "LRUContentStore could not be created. Could not allocate all index tables.", (void *) store, store->objectCapacity); } _destroyIndexes(store); result = false; } else { result = true; } return result; }