Exemple #1
0
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;
}
Exemple #2
0
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(&ether);
        }

        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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #8
0
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;
}