eARNETWORK_ERROR ARNETWORK_Sender_Flush (ARNETWORK_Sender_t *senderPtr) { /** -- Flush all IoBuffer -- */ /** local declarations */ eARNETWORK_ERROR error = ARNETWORK_OK; int inputIndex; ARNETWORK_IOBuffer_t *inputBufferTemp = NULL; /** for each input buffer */ for (inputIndex = 0; inputIndex < senderPtr->numberOfInputBuff && error == ARNETWORK_OK; ++inputIndex) { inputBufferTemp = senderPtr->inputBufferPtrArr[inputIndex]; /** lock the IOBuffer */ error = ARNETWORK_IOBuffer_Lock (inputBufferTemp); if (error == ARNETWORK_OK) { /** flush the IoBuffer */ error = ARNETWORK_IOBuffer_Flush (inputBufferTemp); /** unlock the IOBuffer */ ARNETWORK_IOBuffer_Unlock (inputBufferTemp); } } return error; }
void ARNETWORK_Sender_SendPong (ARNETWORK_Sender_t *senderPtr, uint8_t *data, int dataSize) { ARNETWORK_IOBuffer_t *inputBufferPtrTemp; eARNETWORK_ERROR err = ARNETWORK_OK; inputBufferPtrTemp = senderPtr->inputBufferPtrMap[ARNETWORK_MANAGER_INTERNAL_BUFFER_ID_PONG]; err = ARNETWORK_IOBuffer_Lock (inputBufferPtrTemp); if (err != ARNETWORK_OK) { ARSAL_PRINT (ARSAL_PRINT_ERROR, ARNETWORK_SENDER_TAG, "ARNETWORK_IOBuffer_Lock() failed; error: %s", ARNETWORK_Error_ToString (err)); return; } ARNETWORK_IOBuffer_AddData (inputBufferPtrTemp, data, dataSize, NULL, NULL, 1); ARNETWORK_IOBuffer_Unlock (inputBufferPtrTemp); }
eARNETWORK_ERROR ARNETWORK_Sender_AckReceived (ARNETWORK_Sender_t *senderPtr, int identifier, uint8_t seqNumber) { /** -- Receive an acknowledgment fo a data -- */ /** local declarations */ ARNETWORK_IOBuffer_t *inputBufferPtr = NULL; eARNETWORK_ERROR error = ARNETWORK_OK; inputBufferPtr = senderPtr->inputBufferPtrMap[identifier]; if (inputBufferPtr != NULL) { /** lock the IOBuffer */ error = ARNETWORK_IOBuffer_Lock (inputBufferPtr); if (error == ARNETWORK_OK) { /** * Transmit the acknowledgment to the input buffer. * if the acknowledgment is suiarray the waiting data is popped */ error = ARNETWORK_IOBuffer_AckReceived (inputBufferPtr, seqNumber); /** unlock the IOBuffer */ ARNETWORK_IOBuffer_Unlock (inputBufferPtr); /* Wake up the send thread to update the wait time of buffers */ ARNETWORK_Sender_SignalNewData (senderPtr); } } else { error = ARNETWORK_ERROR_ID_UNKNOWN; } return error; }
void* ARNETWORK_Receiver_ThreadRun (void *data) { /** -- Manage the reception of the data on the Receiver' socket. -- */ /** local declarations */ ARNETWORK_Receiver_t *receiverPtr = data; ARNETWORKAL_Frame_t frame ; ARNETWORK_IOBuffer_t* outBufferPtrTemp = NULL; eARNETWORK_ERROR error = ARNETWORK_OK; eARNETWORKAL_MANAGER_RETURN result = ARNETWORKAL_MANAGER_RETURN_DEFAULT; uint8_t ackSeqNumData = 0; struct timespec now; while (receiverPtr->isAlive) { /** wait a receipt */ if (receiverPtr->networkALManager->receive(receiverPtr->networkALManager) == ARNETWORKAL_MANAGER_RETURN_DEFAULT) { /** for each frame present in the receiver buffer */ result = receiverPtr->networkALManager->popFrame(receiverPtr->networkALManager, &frame); while (result == ARNETWORKAL_MANAGER_RETURN_DEFAULT) { /* Special handling of internal frames */ if (frame.id < ARNETWORK_MANAGER_INTERNAL_BUFFER_ID_MAX) { switch (frame.id) { case ARNETWORK_MANAGER_INTERNAL_BUFFER_ID_PING: /* Ping, send the corresponding pong */ { ARNETWORK_Sender_SendPong (receiverPtr->senderPtr, frame.dataPtr, frame.size - offsetof(ARNETWORKAL_Frame_t, dataPtr)); } break; case ARNETWORK_MANAGER_INTERNAL_BUFFER_ID_PONG: /* Pong, tells the sender that we got a response */ { struct timespec dataTime; memcpy (&dataTime, frame.dataPtr, sizeof (struct timespec)); ARSAL_Time_GetTime(&now); ARNETWORK_Sender_GotPingAck (receiverPtr->senderPtr, &dataTime, &now); } break; default: /* Do nothing as we don't know how to handle it */ break; } } /** management by the command type */ switch (frame.type) { case ARNETWORKAL_FRAME_TYPE_ACK: /** get the acknowledge sequence number from the data */ memcpy (&ackSeqNumData, frame.dataPtr, sizeof(uint8_t)); ARSAL_PRINT (ARSAL_PRINT_VERBOSE, ARNETWORK_RECEIVER_TAG, "[%p] - TYPE: ARNETWORKAL_FRAME_TYPE_ACK | SEQ:%d | ID:%d | SEQ ACK : %d", receiverPtr, receiverPtr, frame.seq, frame.id, ackSeqNumData); /** transmit the acknowledgement to the sender */ error = ARNETWORK_Sender_AckReceived (receiverPtr->senderPtr, ARNETWORK_Manager_IDAckToIDInput (receiverPtr->networkALManager, frame.id), ackSeqNumData); if (error != ARNETWORK_OK) { switch (error) { case ARNETWORK_ERROR_IOBUFFER_BAD_ACK: ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARNETWORK_RECEIVER_TAG, "[%p] Bad acknowledge, error: %s", receiverPtr, ARNETWORK_Error_ToString (error)); break; default: ARSAL_PRINT (ARSAL_PRINT_ERROR, ARNETWORK_RECEIVER_TAG, "[%p] Acknowledge received, error: %s", receiverPtr, ARNETWORK_Error_ToString (error)); break; } } break; case ARNETWORKAL_FRAME_TYPE_DATA: ARSAL_PRINT (ARSAL_PRINT_VERBOSE, ARNETWORK_RECEIVER_TAG, "[%p] - TYPE: ARNETWORKAL_FRAME_TYPE_DATA | SEQ:%d | ID:%d", receiverPtr, frame.seq, frame.id); /** push the data received in the output buffer targeted */ outBufferPtrTemp = receiverPtr->outputBufferPtrMap[frame.id]; if (outBufferPtrTemp != NULL) { /** lock the IOBuffer */ error = ARNETWORK_IOBuffer_Lock(outBufferPtrTemp); if(error == ARNETWORK_OK) { int accept = ARNETWORK_IOBuffer_ShouldAcceptData (outBufferPtrTemp, frame.seq); if (accept > 0) { error = ARNETWORK_Receiver_CopyDataRecv(receiverPtr, outBufferPtrTemp, &frame); } else if (accept == 0) { ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARNETWORK_RECEIVER_TAG, "[%p] Received a retry for buffer %d", receiverPtr, outBufferPtrTemp->ID); } else { ARSAL_PRINT (ARSAL_PRINT_WARNING, ARNETWORK_RECEIVER_TAG, "[%p] Received an old frame for buffer %d", receiverPtr, outBufferPtrTemp->ID); } /** unlock the IOBuffer */ ARNETWORK_IOBuffer_Unlock(outBufferPtrTemp); if(error != ARNETWORK_OK) { ARSAL_PRINT (ARSAL_PRINT_ERROR, ARNETWORK_RECEIVER_TAG, "[%p] data received, error: %s", receiverPtr, ARNETWORK_Error_ToString (error)); } } } break; case ARNETWORKAL_FRAME_TYPE_DATA_LOW_LATENCY: ARSAL_PRINT (ARSAL_PRINT_VERBOSE, ARNETWORK_RECEIVER_TAG, "[%p] - TYPE: ARNETWORKAL_FRAME_TYPE_DATA_LOW_LATENCY | SEQ:%d | ID:%d", receiverPtr, frame.seq, frame.id); /** push the data received in the output buffer targeted */ outBufferPtrTemp = receiverPtr->outputBufferPtrMap[frame.id]; if (outBufferPtrTemp != NULL) { /** lock the IOBuffer */ error = ARNETWORK_IOBuffer_Lock(outBufferPtrTemp); if(error == ARNETWORK_OK) { int accept = ARNETWORK_IOBuffer_ShouldAcceptData (outBufferPtrTemp, frame.seq); if (accept > 0) { error = ARNETWORK_Receiver_CopyDataRecv(receiverPtr, outBufferPtrTemp, &frame); } else if (accept == 0) { ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARNETWORK_RECEIVER_TAG, "[%p] Received a retry for buffer %d", receiverPtr, outBufferPtrTemp->ID); } else { ARSAL_PRINT (ARSAL_PRINT_WARNING, ARNETWORK_RECEIVER_TAG, "[%p] Received an old frame for buffer %d", receiverPtr, outBufferPtrTemp->ID); } /** unlock the IOBuffer */ ARNETWORK_IOBuffer_Unlock(outBufferPtrTemp); if(error != ARNETWORK_OK) { ARSAL_PRINT (ARSAL_PRINT_ERROR, ARNETWORK_RECEIVER_TAG, "[%p] data received, error: %s", receiverPtr, ARNETWORK_Error_ToString (error)); } } } break; case ARNETWORKAL_FRAME_TYPE_DATA_WITH_ACK: ARSAL_PRINT (ARSAL_PRINT_VERBOSE, ARNETWORK_RECEIVER_TAG, "[%p] - TYPE: ARNETWORKAL_FRAME_TYPE_DATA_WITH_ACK | SEQ:%d | ID:%d", receiverPtr, frame.seq, frame.id); /** * push the data received in the output buffer targeted, * save the sequence of the command and return an acknowledgement */ outBufferPtrTemp = receiverPtr->outputBufferPtrMap[frame.id]; if (outBufferPtrTemp != NULL) { /** lock the IOBuffer */ error = ARNETWORK_IOBuffer_Lock(outBufferPtrTemp); if(error == ARNETWORK_OK) { /** OutBuffer->seqWaitAck used to save the last seq */ int accept = ARNETWORK_IOBuffer_ShouldAcceptData (outBufferPtrTemp, frame.seq); if (accept > 0) { error = ARNETWORK_Receiver_CopyDataRecv(receiverPtr, outBufferPtrTemp, &frame); } else if (accept == 0) { ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARNETWORK_RECEIVER_TAG, "[%p] Received a retry for buffer %d", receiverPtr, outBufferPtrTemp->ID); } else { ARSAL_PRINT (ARSAL_PRINT_WARNING, ARNETWORK_RECEIVER_TAG, "[%p] Received an old frame for buffer %d", receiverPtr, outBufferPtrTemp->ID); } /** unlock the IOBuffer */ ARNETWORK_IOBuffer_Unlock(outBufferPtrTemp); // data are copied to the IOBuffer, send ACK if (error == ARNETWORK_OK) { /** sending ack even if the seq is not correct */ error = ARNETWORK_Receiver_ReturnACK(receiverPtr, frame.id, frame.seq); if(error != ARNETWORK_OK) { int level = ARSAL_PRINT_ERROR; if (error == ARNETWORK_ERROR_BUFFER_SIZE) { level = ARSAL_PRINT_DEBUG; } ARSAL_PRINT(level, ARNETWORK_RECEIVER_TAG, "[%p] ReturnACK, error: %s", receiverPtr, ARNETWORK_Error_ToString(error)); } } else { ARSAL_PRINT (ARSAL_PRINT_ERROR, ARNETWORK_RECEIVER_TAG, "[%p] data with ack received, error: %s", receiverPtr, ARNETWORK_Error_ToString (error)); } } } break; default: ARSAL_PRINT (ARSAL_PRINT_WARNING, ARNETWORK_RECEIVER_TAG, "[%p] !!! command type: %d not known !!!", receiverPtr, frame.type); break; } /** get the next frame*/ result = receiverPtr->networkALManager->popFrame(receiverPtr->networkALManager, &frame); } } } return NULL; }
void ARNETWORK_Sender_ProcessBufferToSend (ARNETWORK_Sender_t *senderPtr, ARNETWORK_IOBuffer_t *buffer, int hasWaitedMs) { eARNETWORK_MANAGER_CALLBACK_RETURN callbackReturn = ARNETWORK_MANAGER_CALLBACK_RETURN_DEFAULT; eARNETWORK_ERROR error = ARNETWORK_OK; /** lock the IOBuffer */ error = ARNETWORK_IOBuffer_Lock(buffer); if(error == ARNETWORK_OK) { /** decrement the time to wait */ if ((buffer->waitTimeCount > 0) && (hasWaitedMs > 0)) { if (hasWaitedMs > buffer->waitTimeCount) { buffer->waitTimeCount = 0; } else { buffer->waitTimeCount -= hasWaitedMs; } } if (ARNETWORK_IOBuffer_IsWaitAck (buffer)) { /** decrement the time to wait before considering as a timeout */ if ((buffer->ackWaitTimeCount > 0) && (hasWaitedMs > 0)) { if (hasWaitedMs > buffer->ackWaitTimeCount) { buffer->ackWaitTimeCount = 0; } else { buffer->ackWaitTimeCount -= hasWaitedMs; } } if (buffer->ackWaitTimeCount == 0) { ARSAL_PRINT(ARSAL_PRINT_ERROR, ARNETWORK_SENDER_TAG, "[%p] Timeout waiting for ack in buffer %d", senderPtr, buffer->ID); if (buffer->retryCount == 0) { /** if there are timeout and too sending retry ... */ ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARNETWORK_SENDER_TAG, "!!! too retry !!!"); callbackReturn = ARNETWORK_Sender_TimeOutCallback (senderPtr, buffer); ARNETWORK_Sender_ManageTimeOut (senderPtr, buffer, callbackReturn); } else { /** if there is a timeout, retry to send the data */ ARSAL_PRINT(ARSAL_PRINT_ERROR, ARNETWORK_SENDER_TAG, "[%p] Will retry sending data of buffer %d", senderPtr, buffer->ID); error = ARNETWORK_Sender_AddToBuffer (senderPtr, buffer, 1); if (error == ARNETWORK_OK) { /** reset the timeout counter*/ buffer->ackWaitTimeCount = buffer->ackTimeoutMs; /** decrement the number of retry still possible is retryCount isn't -1 */ if (buffer->retryCount > 0) { -- (buffer->retryCount); } } } } } else if ((!ARNETWORK_RingBuffer_IsEmpty (buffer->dataDescriptorRBuffer)) && (buffer->waitTimeCount == 0)) { /** try to add the latest data of the input buffer in the sending buffer; callback with sent status */ if (ARNETWORK_Sender_AddToBuffer (senderPtr, buffer, 0) == ARNETWORK_OK) { buffer->waitTimeCount = buffer->sendingWaitTimeMs; switch (buffer->dataType) { case ARNETWORKAL_FRAME_TYPE_DATA_WITH_ACK: /** * reinitialize the input buffer parameters, * save the sequence wait for the acknowledgement, * and pass on waiting acknowledgement. */ buffer->isWaitAck = 1; buffer->ackWaitTimeCount = buffer->ackTimeoutMs; buffer->retryCount = buffer->numberOfRetry; break; case ARNETWORKAL_FRAME_TYPE_DATA: /** pop the data sent */ ARNETWORK_IOBuffer_PopData (buffer); break; case ARNETWORKAL_FRAME_TYPE_DATA_LOW_LATENCY: /** pop the data sent */ ARNETWORK_IOBuffer_PopData (buffer); break; case ARNETWORKAL_FRAME_TYPE_ACK: /** pop the acknowledgement sent */ ARNETWORK_IOBuffer_PopData (buffer); break; default: ARSAL_PRINT (ARSAL_PRINT_ERROR, ARNETWORK_SENDER_TAG, "[%p] dataType: %d unknow \n", senderPtr, buffer->dataType); break; } } } /** unlock the IOBuffer */ ARNETWORK_IOBuffer_Unlock(buffer); } }
void* ARNETWORK_Sender_ThreadRun (void* data) { /** -- Manage the sending of the data on the sender' -- */ /** local declarations */ ARNETWORK_Sender_t *senderPtr = data; int inputBufferIndex = 0; ARNETWORK_IOBuffer_t *inputBufferPtrTemp = NULL; /**< pointer of the input buffer in processing */ eARNETWORK_ERROR error = ARNETWORK_OK; int waitTimeMs = 0; struct timespec now; struct timespec sleepStart; int sleepDurationMs = 0; int timeDiffMs; while (senderPtr->isAlive) { waitTimeMs = 500; for (inputBufferIndex = 0; inputBufferIndex < senderPtr->numberOfInputBuff && waitTimeMs > 0; ++inputBufferIndex) { inputBufferPtrTemp = senderPtr->inputBufferPtrArr[inputBufferIndex]; error = ARNETWORK_IOBuffer_Lock(inputBufferPtrTemp); switch (inputBufferPtrTemp->dataType) { // Low latency : no wait if any data available case ARNETWORKAL_FRAME_TYPE_DATA_LOW_LATENCY: if ((error == ARNETWORK_OK) && (!ARNETWORK_RingBuffer_IsEmpty (inputBufferPtrTemp->dataDescriptorRBuffer))) { waitTimeMs = 0; } break; // Acknowledged buffer : // - If waiting an ack, wait time = time before ack timeout // - If not waiting an ack and not empty, wait time = time before next send case ARNETWORKAL_FRAME_TYPE_DATA_WITH_ACK: if (error == ARNETWORK_OK) { if (ARNETWORK_IOBuffer_IsWaitAck(inputBufferPtrTemp)) { if (inputBufferPtrTemp->ackWaitTimeCount < waitTimeMs) { waitTimeMs = inputBufferPtrTemp->ackWaitTimeCount; } } else if (!ARNETWORK_RingBuffer_IsEmpty (inputBufferPtrTemp->dataDescriptorRBuffer)) { if (inputBufferPtrTemp->waitTimeCount < waitTimeMs) { waitTimeMs = inputBufferPtrTemp->waitTimeCount; } } } break; // All non Ack buffers // - default: if ((error == ARNETWORK_OK) && (!ARNETWORK_RingBuffer_IsEmpty (inputBufferPtrTemp->dataDescriptorRBuffer))) { if (inputBufferPtrTemp->waitTimeCount < waitTimeMs) { waitTimeMs = inputBufferPtrTemp->waitTimeCount; } } break; } ARNETWORK_IOBuffer_Unlock(inputBufferPtrTemp); } // Force a minimum wait time after an ARNetworkAL Overflow if ((senderPtr->hadARNetworkALOverflowOnPreviousRun > 0) && (waitTimeMs < ARNETWORK_SENDER_WAIT_TIME_ON_ARNETWORKAL_OVERFLOW_MS)) { waitTimeMs = ARNETWORK_SENDER_WAIT_TIME_ON_ARNETWORKAL_OVERFLOW_MS; } senderPtr->hadARNetworkALOverflowOnPreviousRun = 0; ARSAL_Time_GetTime(&sleepStart); if (waitTimeMs > 0) { if (waitTimeMs < senderPtr->minimumTimeBetweenSendsMs) { waitTimeMs = senderPtr->minimumTimeBetweenSendsMs; } ARSAL_Mutex_Lock (&(senderPtr->nextSendMutex)); ARSAL_Cond_Timedwait (&(senderPtr->nextSendCond), &(senderPtr->nextSendMutex), waitTimeMs); ARSAL_Mutex_Unlock (&(senderPtr->nextSendMutex)); } /** Process internal input buffers */ ARSAL_Time_GetTime(&now); sleepDurationMs = ARSAL_Time_ComputeTimespecMsTimeDiff (&sleepStart, &now); ARSAL_Mutex_Lock (&(senderPtr->pingMutex)); timeDiffMs = ARSAL_Time_ComputeTimespecMsTimeDiff (&(senderPtr->pingStartTime), &now); /* Send only new pings if ping function is active (min time > 0) */ if (senderPtr->minTimeBetweenPings > 0) { int maxWaitTime = senderPtr->minTimeBetweenPings; if (ARNETWORK_SENDER_PING_TIMEOUT_MS > maxWaitTime) { maxWaitTime = ARNETWORK_SENDER_PING_TIMEOUT_MS; } /* Send new ping if : * -> DT > minTimeBetweenPings AND we're not waiting for a ping * -> DT > maxWaitTime */ if (((senderPtr->isPingRunning == 0) && (timeDiffMs > senderPtr->minTimeBetweenPings)) || (timeDiffMs > maxWaitTime)) { if (timeDiffMs > ARNETWORK_SENDER_PING_TIMEOUT_MS) { senderPtr->lastPingValue = -1; } inputBufferPtrTemp = senderPtr->inputBufferPtrMap[ARNETWORK_MANAGER_INTERNAL_BUFFER_ID_PING]; error = ARNETWORK_IOBuffer_Lock (inputBufferPtrTemp); if (error == ARNETWORK_OK) { ARNETWORK_IOBuffer_AddData (inputBufferPtrTemp, (uint8_t *)&now, sizeof (now), NULL, NULL, 1); ARNETWORK_IOBuffer_Unlock (inputBufferPtrTemp); } else { ARSAL_PRINT (ARSAL_PRINT_ERROR, ARNETWORK_SENDER_TAG, "ARNETWORK_IOBuffer_Lock() failed; error: %s", ARNETWORK_Error_ToString (error)); } senderPtr->pingStartTime.tv_sec = now.tv_sec; senderPtr->pingStartTime.tv_nsec = now.tv_nsec; senderPtr->isPingRunning = 1; } } ARSAL_Mutex_Unlock (&(senderPtr->pingMutex)); for (inputBufferIndex = 0; inputBufferIndex < senderPtr->networkALManager->maxIds ; inputBufferIndex++) { inputBufferPtrTemp = senderPtr->inputBufferPtrMap[inputBufferIndex]; if (inputBufferPtrTemp != NULL) { ARNETWORK_Sender_ProcessBufferToSend (senderPtr, inputBufferPtrTemp, (waitTimeMs > 0) ? sleepDurationMs : 0); } } senderPtr->networkALManager->send(senderPtr->networkALManager); } return NULL; }