LONGBOW_TEST_CASE(Global, metisMessage_Copy) { char message_str[] = "\x00Once upon a time, in a stack far away, a dangling pointer found its way to the top of the heap."; PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, message_str, sizeof(message_str)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); metisLogger_Release(&logger); assertNotNull(message, "Got null from metisMessage_CreateFromBuffer"); assertTrue(message->refcount == 1, "Incorrect refcount, expected %u got %u", 1, message->refcount); MetisMessage *copy = metisMessage_Acquire(message); assertTrue(message->refcount == 2, "Incorrect refcount, expected %u got %u", 2, message->refcount); metisMessage_Release(&message); assertTrue(copy->refcount == 1, "Incorrect refcount, expected %u got %u", 1, message->refcount); metisMessage_Release(©); assertTrue(parcMemory_Outstanding() == 0, "Memory balance should be zero after destroying last copy, got %u", parcMemory_Outstanding()); }
LONGBOW_TEST_CASE(Global, metisMessage_ReadFromBuffer) { char message_str[] = "\x00Once upon a time, in a stack far away, a dangling pointer found its way to the top of the heap."; PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, message_str, sizeof(message_str)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_ReadFromBuffer(1, 2, buff, sizeof(message_str), logger); metisLogger_Release(&logger); assertNotNull(message, "Got null from metisMessage_CreateFromBuffer"); assertTrue(parcEventBuffer_GetLength(message->messageBytes) == sizeof(message_str), "Length of internal buffer wrong, expected %zu got %zu", sizeof(message_str), parcEventBuffer_GetLength(message->messageBytes)); uint8_t *p = parcEventBuffer_Pullup(message->messageBytes, sizeof(message_str)); assertTrue(memcmp(p, message_str, sizeof(message_str)) == 0, "Internal buffer contents does not match test"); assertTrue(message->ingressConnectionId == 1, "IngressConnectionId wrong, expected %d got %u", 1, message->ingressConnectionId); assertTrue(message->receiveTime == 2, "receiveTime wrong, expected %u got %" PRIu64, 2, message->receiveTime); assertTrue(parcEventBuffer_GetLength(buff) == 0, "Origin buffer not drained, expected 0, got %zu", parcEventBuffer_GetLength(buff)); metisMessage_Release(&message); parcEventBuffer_Destroy(&buff); }
/* * We've reach the END fragment of the reassembly buffer. * 1) Make a metis message out of the reassembly buffer, * 2) put the message in the receive queue (discard if queue full) * 3) allocate a new reassembly buffer * 4) reset the parser */ static void _finalizeReassemblyBuffer(MetisHopByHopFragmenter *fragmenter) { // This takes ownership of fragmenter->currentReceiveBuffer MetisMessage *reassembled = metisMessage_CreateFromBuffer(fragmenter->currentReceiveBufferIngressId, fragmenter->currentReceiveBufferStartTicks, fragmenter->currentReceiveBuffer, fragmenter->logger); if (reassembled) { bool success = parcRingBuffer1x1_Put(fragmenter->receiveQueue, reassembled); if (success) { metisLogger_Log(fragmenter->logger, MetisLoggerFacility_IO, PARCLogLevel_Debug, __func__, "Fragmenter %p putting reassembed message %p in receive queue", (void *) fragmenter, (void *) reassembled); } else { metisLogger_Log(fragmenter->logger, MetisLoggerFacility_IO, PARCLogLevel_Error, __func__, "Fragmenter %p failed to put reassembled message in receive queue, dropping", (void *) fragmenter); metisMessage_Release(&reassembled); } fragmenter->currentReceiveBuffer = parcEventBuffer_Create(); } else { metisLogger_Log(fragmenter->logger, MetisLoggerFacility_IO, PARCLogLevel_Warning, __func__, "Fragmenter %p failed to parse reassembled packet to MetisMessage, dropping", (void *) fragmenter); } _resetParser(fragmenter); }
LONGBOW_TEST_CASE(Global, metisMessage_Append) { char message_str[] = "\x00Once upon a time ..."; PARCEventBuffer *buffer = parcEventBuffer_Create(); PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, message_str, sizeof(message_str)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); int result = metisMessage_Append(buffer, message); assertTrue(result == 0, "Got error from metisMessage_Append"); metisLogger_Release(&logger); metisMessage_Release(&message); parcEventBuffer_Destroy(&buffer); }
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; }
LONGBOW_TEST_CASE(Global, metisMessage_HasInterestLifetime) { PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, metisTestDataV1_Interest_AllFields, sizeof(metisTestDataV1_Interest_AllFields)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); metisLogger_Release(&logger); assertTrue(metisMessage_HasInterestLifetime(message), "Should have returned true for interest lifetime"); metisMessage_Release(&message); }
LONGBOW_TEST_CASE(Global, metisMessage_GetInterestLifetimeTicks) { PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, metisTestDataV1_Interest_AllFields, sizeof(metisTestDataV1_Interest_AllFields)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); metisLogger_Release(&logger); // don't check actual value. It will vary based on METISHZ and rouding errors due to integer math MetisTicks ticks = metisMessage_GetInterestLifetimeTicks(message); assertTrue(ticks > 0, "Should have gotten positive value for interest lifetime ticks"); metisMessage_Release(&message); }
LONGBOW_TEST_CASE(Global, metisMessage_Create_InterestV1) { PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, metisTestDataV1_Interest_AllFields, sizeof(metisTestDataV1_Interest_AllFields)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); metisLogger_Release(&logger); assertNotNull(message, "Got null from metisMessage_CreateFromBuffer"); assertTrue(message->ingressConnectionId == 1, "IngressConnectionId wrong, expected %d got %u", 1, message->ingressConnectionId); assertTrue(message->receiveTime == 2, "receiveTime wrong, expected %u got %" PRIu64, 2, message->receiveTime); metisMessage_Release(&message); }
LONGBOW_TEST_CASE(Global, metisMessage_CreateFromBuffer_BadMessage) { // Bad version char message_str[] = "\xFFOnce upon a time, in a stack far away, a dangling pointer found its way to the top of the heap."; printf("metisMessage_CreateFromBuffer_BadMessage attempting to process a bad message which should report an error:\n"); PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, message_str, sizeof(message_str)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); metisLogger_Release(&logger); assertNull(message, "Got null from metisMessage_CreateFromBuffer"); }
LONGBOW_TEST_CASE(Global, metisMessage_Length) { char message_str[] = "\x00Once upon a time, in a stack far away, a dangling pointer found its way to the top of the heap."; PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, message_str, sizeof(message_str)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); metisLogger_Release(&logger); assertNotNull(message, "Got null from metisMessage_CreateFromBuffer"); size_t length = metisMessage_Length(message); assertTrue(length == sizeof(message_str), "Wrong length, expected %zu got %zu", sizeof(message_str), length); metisMessage_Release(&message); }
LONGBOW_TEST_CASE(Global, metisMessage_GetReceiveTime) { char message_str[] = "\x00Once upon a time, in a stack far away, a dangling pointer found its way to the top of the heap."; PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, message_str, sizeof(message_str)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); metisLogger_Release(&logger); assertNotNull(message, "Got null from metisMessage_CreateFromBuffer"); MetisTicks time = metisMessage_GetReceiveTime(message); assertTrue(time == 2, "Wrong receive time, expected %u got %" PRIu64, 2, time); metisMessage_Release(&message); }
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; }
LONGBOW_TEST_CASE(Global, metisMessage_Write) { char message_str[] = "\x00Once upon a time ..."; PARCEventScheduler *scheduler = parcEventScheduler_Create(); PARCEventQueue *queue = parcEventQueue_Create(scheduler, -1, PARCEventQueueOption_CloseOnFree); PARCEventBuffer *buff = parcEventBuffer_Create(); parcEventBuffer_Append(buff, message_str, sizeof(message_str)); PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); parcLogReporter_Release(&reporter); MetisMessage *message = metisMessage_CreateFromBuffer(1, 2, buff, logger); int result = metisMessage_Write(queue, message); assertTrue(result == 0, "Got error from metisMessage_Write"); // buff is deallocated by metisMessage_Release metisLogger_Release(&logger); metisMessage_Release(&message); parcEventQueue_Destroy(&queue); parcEventScheduler_Destroy(&scheduler); }