PARCEventQueue * metisDispatcher_CreateStreamBufferFromSocket(MetisDispatcher *dispatcher, MetisSocketType fd) { assertNotNull(dispatcher, "Parameter dispatcher must be non-null"); PARCEventQueue *buffer = parcEventQueue_Create(dispatcher->Base, fd, PARCEventQueueOption_CloseOnFree | PARCEventQueueOption_DeferCallbacks); assertNotNull(buffer, "Got null from parcEventBufver_Create for socket %d", fd); return buffer; }
/** * Connect to an INET peer * @return NULL on error, otherwise a streambuffer */ static PARCEventQueue * metisDispatcher_StreamBufferConnect_INET(MetisDispatcher *dispatcher, const CPIAddress *localAddress, const CPIAddress *remoteAddress) { struct sockaddr_in localSock, remoteSock; cpiAddress_GetInet(localAddress, &localSock); cpiAddress_GetInet(remoteAddress, &remoteSock); PARCEventQueue *buffer = parcEventQueue_Create(dispatcher->Base, -1, PARCEventQueueOption_CloseOnFree); assertNotNull(buffer, "got null buffer from parcEventQueue_Create()"); bool success = metisDispatcher_StreamBufferBindAndConnect(dispatcher, buffer, (struct sockaddr *) &localSock, sizeof(localSock), (struct sockaddr *) &remoteSock, sizeof(remoteSock)); if (!success) { parcEventQueue_Destroy(&buffer); buffer = NULL; } return buffer; }
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; }
/** * Creates a client-specific session * * <#Discussion#> * * @param <#param1#> * @return <#return#> * * Example: * @code * <#example#> * @endcode */ static _MetisCommandLineInterface_Session * metisCliSession_Create(MetisCommandLineInterface *cli, MetisSocketType clientSocket, struct sockaddr *clientAddress, int clientAddressLength) { _MetisCommandLineInterface_Session *session = parcMemory_AllocateAndClear(sizeof(_MetisCommandLineInterface_Session)); assertNotNull(session, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(_MetisCommandLineInterface_Session)); session->parentCli = cli; session->clientAddress = parcMemory_Allocate(clientAddressLength); assertNotNull(session->clientAddress, "parcMemory_Allocate(%d) returned NULL", clientAddressLength); session->clientAddressLength = clientAddressLength; session->clientSocket = clientSocket; memcpy(session->clientAddress, clientAddress, clientAddressLength); MetisDispatcher *dispatcher = metisForwarder_GetDispatcher(cli->metis); PARCEventScheduler *eventBase = metisDispatcher_GetEventScheduler(dispatcher); session->streamBuffer = parcEventQueue_Create(eventBase, clientSocket, PARCEventQueueOption_CloseOnFree | PARCEventQueueOption_DeferCallbacks); parcEventQueue_SetCallbacks(session->streamBuffer, _metisCliSession_ReadCallback, NULL, _metisCliSession_EventCallback, session); parcEventQueue_Enable(session->streamBuffer, PARCEventType_Read); return session; }
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); }