Пример #1
0
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));
        }
    }
}
Пример #2
0
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;
}
Пример #3
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));
}