void ARSTREAM_Reader_StopReader (ARSTREAM_Reader_t *reader) { if (reader != NULL) { reader->threadsShouldStop = 1; /* Force unblock the ACK thread to allow it to shutdown quickly. * This is necessary if maxAckInterval is set to -1, 0 or a large value. * If maxAckInterval >= 0, an ACK packet will be sent as a side-effect. */ if (reader->ackThreadStarted == 1) { ARSAL_Mutex_Lock (&(reader->ackSendMutex)); ARSAL_Cond_Signal (&(reader->ackSendCond)); ARSAL_Mutex_Unlock (&(reader->ackSendMutex)); } } }
void* ARSTREAM_Reader_RunDataThread (void *ARSTREAM_Reader_t_Param) { uint8_t *recvData = NULL; int recvSize; uint16_t previousFNum = UINT16_MAX; int skipCurrentFrame = 0; int packetWasAlreadyAck = 0; ARSTREAM_Reader_t *reader = (ARSTREAM_Reader_t *)ARSTREAM_Reader_t_Param; ARSTREAM_NetworkHeaders_DataHeader_t *header = NULL; int recvDataLen = reader->maxFragmentSize + sizeof (ARSTREAM_NetworkHeaders_DataHeader_t); /* Parameters check */ if (reader == NULL) { ARSAL_PRINT (ARSAL_PRINT_ERROR, ARSTREAM_READER_TAG, "Error while starting %s, bad parameters", __FUNCTION__); return (void *)0; } /* Alloc and check */ recvData = malloc (recvDataLen); if (recvData == NULL) { ARSAL_PRINT (ARSAL_PRINT_ERROR, ARSTREAM_READER_TAG, "Error while starting %s, can not alloc memory", __FUNCTION__); return (void *)0; } header = (ARSTREAM_NetworkHeaders_DataHeader_t *)recvData; ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Stream reader thread running"); reader->dataThreadStarted = 1; while (reader->threadsShouldStop == 0) { eARNETWORK_ERROR err = ARNETWORK_Manager_ReadDataWithTimeout (reader->manager, reader->dataBufferID, recvData, recvDataLen, &recvSize, ARSTREAM_READER_DATAREAD_TIMEOUT_MS); if (ARNETWORK_OK != err) { if (ARNETWORK_ERROR_BUFFER_EMPTY != err) { ARSAL_PRINT (ARSAL_PRINT_ERROR, ARSTREAM_READER_TAG, "Error while reading stream data: %s", ARNETWORK_Error_ToString (err)); } } else { int cpIndex, cpSize, endIndex; ARSAL_Mutex_Lock (&(reader->ackPacketMutex)); if (header->frameNumber != reader->ackPacket.frameNumber) { reader->efficiency_index ++; reader->efficiency_index %= ARSTREAM_READER_EFFICIENCY_AVERAGE_NB_FRAMES; reader->efficiency_nbTotal [reader->efficiency_index] = 0; reader->efficiency_nbUseful [reader->efficiency_index] = 0; skipCurrentFrame = 0; reader->currentFrameSize = 0; reader->ackPacket.frameNumber = header->frameNumber; #ifdef DEBUG uint32_t nackPackets = ARSTREAM_NetworkHeaders_AckPacketCountNotSet (&(reader->ackPacket), header->fragmentsPerFrame); if (nackPackets != 0) { ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Dropping a frame (missing %d fragments)", nackPackets); } #endif ARSTREAM_NetworkHeaders_AckPacketResetUpTo (&(reader->ackPacket), header->fragmentsPerFrame); } packetWasAlreadyAck = ARSTREAM_NetworkHeaders_AckPacketFlagIsSet (&(reader->ackPacket), header->fragmentNumber); ARSTREAM_NetworkHeaders_AckPacketSetFlag (&(reader->ackPacket), header->fragmentNumber); reader->efficiency_nbTotal [reader->efficiency_index] ++; if (packetWasAlreadyAck == 0) { reader->efficiency_nbUseful [reader->efficiency_index] ++; } ARSAL_Mutex_Unlock (&(reader->ackPacketMutex)); ARSAL_Mutex_Lock (&(reader->ackSendMutex)); ARSAL_Cond_Signal (&(reader->ackSendCond)); ARSAL_Mutex_Unlock (&(reader->ackSendMutex)); cpIndex = reader->maxFragmentSize * header->fragmentNumber; cpSize = recvSize - sizeof (ARSTREAM_NetworkHeaders_DataHeader_t); endIndex = cpIndex + cpSize; while ((endIndex > reader->currentFrameBufferSize) && (skipCurrentFrame == 0) && (packetWasAlreadyAck == 0)) { uint32_t nextFrameBufferSize = reader->maxFragmentSize * header->fragmentsPerFrame; uint32_t dummy; uint8_t *nextFrameBuffer = reader->callback (ARSTREAM_READER_CAUSE_FRAME_TOO_SMALL, reader->currentFrameBuffer, reader->currentFrameSize, 0, 0, &nextFrameBufferSize, reader->custom); if (nextFrameBufferSize >= reader->currentFrameSize && nextFrameBufferSize > 0) { memcpy (nextFrameBuffer, reader->currentFrameBuffer, reader->currentFrameSize); } else { skipCurrentFrame = 1; } //TODO: Add "SKIP_FRAME" reader->callback (ARSTREAM_READER_CAUSE_COPY_COMPLETE, reader->currentFrameBuffer, reader->currentFrameSize, 0, skipCurrentFrame, &dummy, reader->custom); reader->currentFrameBuffer = nextFrameBuffer; reader->currentFrameBufferSize = nextFrameBufferSize; } if (skipCurrentFrame == 0) { if (packetWasAlreadyAck == 0) { memcpy (&(reader->currentFrameBuffer)[cpIndex], &recvData[sizeof (ARSTREAM_NetworkHeaders_DataHeader_t)], recvSize - sizeof (ARSTREAM_NetworkHeaders_DataHeader_t)); } if (endIndex > reader->currentFrameSize) { reader->currentFrameSize = endIndex; } ARSAL_Mutex_Lock (&(reader->ackPacketMutex)); if (ARSTREAM_NetworkHeaders_AckPacketAllFlagsSet (&(reader->ackPacket), header->fragmentsPerFrame)) { if (header->frameNumber != previousFNum) { int nbMissedFrame = 0; int isFlushFrame = ((header->frameFlags & ARSTREAM_NETWORK_HEADERS_FLAG_FLUSH_FRAME) != 0) ? 1 : 0; ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Ack all in frame %d (isFlush : %d)", header->frameNumber, isFlushFrame); if (header->frameNumber != previousFNum + 1) { nbMissedFrame = header->frameNumber - previousFNum - 1; ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Missed %d frames !", nbMissedFrame); } previousFNum = header->frameNumber; skipCurrentFrame = 1; reader->currentFrameBuffer = reader->callback (ARSTREAM_READER_CAUSE_FRAME_COMPLETE, reader->currentFrameBuffer, reader->currentFrameSize, nbMissedFrame, isFlushFrame, &(reader->currentFrameBufferSize), reader->custom); } } ARSAL_Mutex_Unlock (&(reader->ackPacketMutex)); } } } free (recvData); reader->callback (ARSTREAM_READER_CAUSE_CANCEL, reader->currentFrameBuffer, reader->currentFrameSize, 0, 0, &(reader->currentFrameBufferSize), reader->custom); ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Stream reader thread ended"); reader->dataThreadStarted = 0; return (void *)0; }
int ARSAL_Sem_Post(ARSAL_Sem_t *sem) { int result = -1; if (NULL == sem || NULL == *sem) { errno = EINVAL; return result; } /* No else. */ #if __SAL_USE_POSIX_SEM result = sem_post ((sem_t *)*sem); #else /* * Custom post algo: * Lock mutex * Increment counter * Unlock mutex * Signal condition */ ARSAL_Sem_CustomImpl_t *psem = (ARSAL_Sem_CustomImpl_t *)*sem; int unlockRes = 0; result = ARSAL_Mutex_Lock (&(psem->lock)); ARSAL_SEM_ERRNO_TRANSFORM (result); if (0 == result) { if (INT32_MAX == psem->count) { result = -1; errno = EOVERFLOW; } else { (psem->count)++; } } /* No else. */ unlockRes = ARSAL_Mutex_Unlock (&(psem->lock)); if (0 != unlockRes) { result = -1; errno = unlockRes; } /* No else. */ if (0 == result) { result = ARSAL_Cond_Signal (&(psem->cond)); ARSAL_SEM_ERRNO_TRANSFORM (result); } /* No else. */ #endif return result; }
void ARNETWORK_Sender_SignalNewData (ARNETWORK_Sender_t *senderPtr) { ARSAL_Cond_Signal (&(senderPtr->nextSendCond)); }