예제 #1
0
uint32_t dtm_wait(void)
{
    // Enable wake-up on event
    SCB->SCR |= SCB_SCR_SEVONPEND_Msk;

    for (;;)
    {
        // Event may be the reception of a packet -
        // handle radio first, to give it highest priority:
        if (NRF_RADIO->EVENTS_END != 0)
        {
            NRF_RADIO->EVENTS_END = 0;
            NVIC_ClearPendingIRQ(RADIO_IRQn);

            if (m_state == STATE_RECEIVER_TEST)
            {
                NRF_RADIO->TASKS_RXEN = 1;
                if ((NRF_RADIO->CRCSTATUS == 1) && check_pdu())
                {
                    // Count the number of successfully received packets
                    m_rx_pkt_count++;
                }
                // Note that failing packets are simply ignored (CRC or contents error).

                // Zero fill all pdu fields to avoid stray data
                memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE);
            }
            // If no RECEIVER_TEST is running, ignore incoming packets (but do clear IRQ!)
        }

        // Check for timeouts:
        if (mp_timer->EVENTS_COMPARE[0] != 0)
        {
            mp_timer->EVENTS_COMPARE[0] = 0;
        }
        else if (mp_timer->EVENTS_COMPARE[1] != 0)
        {
            // Reset timeout event flag for next iteration.
            mp_timer->EVENTS_COMPARE[1] = 0;
            NVIC_ClearPendingIRQ(m_timer_irq);
            return ++m_current_time;
        }

        // Other events: No processing
    }
}
예제 #2
0
void process_pdu( tNode* pNode, tpPDU pPDU ) {

    IAnnexEPayloadHeader*   pPayload;
    BOOL                    fError = FALSE;
    int                     nCurPayload = 0;
    int                     nBytesAvail = pPDU->nSize;
    int                     i, cnt, nSz;
    BOOL                    fResendForced = FALSE;
    UINT32                  seqn;

    remote_host_is_alive( pNode );

    seqn = ntoh24( &pPDU->PDU[IAnnexEHeader_SEQN] );
    /* Check for duplicated PDU's. That check is posible only for PDU's with set A-flag!*/
    if (AEHGet_A( pPDU->PDU ) != 0) {
        if (is_old_seqn( seqn, pNode->nLast_Ack_SEQ )) {
            /* duplicate!
             An Ack is send immediately in order to unblock remote annexe module */
            msaPrintFormat( pNode->pAnnexE->msaType, "Duplicate PDU received! send Ack immediately." );
            send_ack( pNode, seqn, TRUE );
            return;
        }
        if (check_pdu( pPDU )) {
            pNode->nLast_Ack_SEQ = seqn;

            if (pNode->pWaitingForAckPDU != NULL)
                send_ack( pNode, seqn, TRUE );
            else
                send_ack( pNode, seqn, FALSE );
        }
    }

    /* get first payload!   */
    if (AEHGet_L( pPDU->PDU ) != 0) {
        /* this is valid only for Annex E over TCP, but it is possible that
            the host implementation of Annex E to not understand it.*/
        pPayload = (IAnnexEPayloadHeader*)(pPDU->PDU + 8);
    }
    else {
        pPayload = (IAnnexEPayloadHeader*)(pPDU->PDU + 4);
        nBytesAvail -= 4;
    }

    /* a cycle to walk through all payloads in the PDU  */
    while ((void*)pPayload < (void*)(&pPDU->PDU[pPDU->nSize])) {
        switch (AEPGet_T( *pPayload )) {
        case AEPT_TransportMessage: {
            /***************************************************************/
            /* T == 00 * Annex E Transport Messages                        */
            /***************************************************************/
            IAnnexET00Header* pTrPayload = (IAnnexET00Header*)(pPayload);

            /* check 'Source/Dest' and 'Session' flags in payload header */
            if ((AEPGet_A( *pPayload ) != 0) || (AEPGet_S( *pPayload ) != 0)) {
                /* this is not a valid Annex E Transport message!
                   send NACK REASON_6:"Payload Corrupted" */
                send_nack6( pNode, seqn, nCurPayload, TRUE );

                /* break the processing of the rest payloads as there is no
                   guarantee that the size of packet may be found correctly. */
                fError = TRUE;
                break;
            }

            switch (pTrPayload[IAnnexET00Header_TRANSPORT_TYPE]) {
            case AEPT00_IAmAlive:
                /* check size of payload! */
                nSz = sizeof_IAmAlive( pTrPayload );
                nBytesAvail -= nSz;
                if (nBytesAvail < 0) {
                    /* incorrect payload size! payload corrupted! */
                    send_nack6( pNode, seqn, nCurPayload, TRUE );
                    fError = TRUE;
                    break;
                }
                if (IMAGet_P( AsIAmAlive( pTrPayload ) )) {
                    /* I_Am_Alive message from remote AnnexE module, return
                       the same payload, with 'P' flag cleared!*/
                    i_am_alive_request_received( pNode, AsIAmAlive( pTrPayload ) );
                }
                else {
                    /* answer to our I-Am-Alive payload!    */
                    i_am_alive_response_received( pNode, AsIAmAlive( pTrPayload ) );
                }
                pPayload = MoveToNextPayload( pPayload, sizeof_IAmAlive( pTrPayload ) );
                break;
            case AEPT00_Ack:
                /*  check size of payload! */
                nSz = sizeof_Ack( pTrPayload );
                nBytesAvail -= nSz;
                if (nBytesAvail < 0) {
                    /*  incorrect payload size! payload corrupted! */
                    send_nack6( pNode, seqn, nCurPayload, TRUE );
                    fError = TRUE;
                    break;
                }
                /* as the current implementation of Annex E fulfills only the
                 'Serial' model, we are interested only of ACK.SEQN equal to
                 that waiting for acknowledge.*/
                if (pNode->pWaitingForAckPDU != NULL) {
                    UINT32  waiting_seqn = ntoh24( &pNode->pWaitingForAckPDU->PDU[IAnnexEHeader_SEQN] );
                    cnt = countof_AckData( pTrPayload );
                    for (i = 0; i < cnt; i++) {
                        UINT32 ack_seqn = ntoh24( &(AsAck( pTrPayload )[IAnnexET00Ack_ACK+
                                                                        i*sizeof_IAnnexEAckData+
                                                                        IAnnexEAckData_SEQNUM]) );
                        if (ack_seqn == waiting_seqn) {
                            ack_received( pNode );
                            break;
                        }
                    }
                }
                pPayload = MoveToNextPayload( pPayload, nSz );
                break;
            case AEPT00_NAck: {
                    IAnnexENAckReason*  pReason = AsNAckReason( GetNAckReasonPtr( pTrPayload ) );
                    /*  check size of payload! */
                    nSz = sizeof_IAnnexET00NAckHeader;
                    nBytesAvail -= nSz;
                    if (nBytesAvail < 0) {
                        /* incorrect payload size! payload corrupted! */
                        send_nack6( pNode, seqn, nCurPayload, TRUE );
                        fError = TRUE;
                        break;
                    }
                    cnt = countof_NAckReasons( pTrPayload );
                    for (i = 0; i < cnt; i++) {
                        UINT16  nReason;
                        UINT32  reason_seqn;
                        /* check size of reason */
                        nSz = sizeof_NAckReason( pReason );
                        nBytesAvail -= nSz;
                        if (nBytesAvail < 0) {
                            /* incorrect payload size! payload corrupted! */
                            send_nack6( pNode, seqn, nCurPayload, TRUE );
                            fError = TRUE;
                            break;
                        }

                        /*  process pReason */
                        nReason = ntoh16( &pReason[IAnnexENAckReason_REASON] );
                        reason_seqn = ntoh24( &pReason[IAnnexENAckReason_SEQNUM] );
                        switch (nReason) {
                        case 0:
                            /* NAck.REASON = Non-Standart Reason
                             not supported by this implementation of Annex E! Skipped!*/
                            break;
                        case 1:
                            /* NAck.REASON = Request the sender to use an alternate port
                             for the specified static payload type. That Nack is of
                             interest only if static type == 0 => (H.225) payload!*/
                            if (AsNAckReason1( pReason )[IAnnexENAckReason1_STATIC_TYPE] == 0) {
                                use_alternate_port( pNode,
                                                    ntoh32( &AsNAckReason1(pReason)[IAnnexENAckReason1_ALTERNATE_IP] ),
                                                    ntoh16( &AsNAckReason1(pReason)[IAnnexENAckReason1_ALTERNATE_PORT] ) );
                            }
                            break;
                        case 2:
                            /* NAck.REASON = Request the sender to use an alternate port
                             for the specified ObjectID payload type

                             not supported in that implementation of Annex E => it is not possible
                             for us to have sent such payload. Possible line error.
                             No reaction currently. It is possible that the next payload is
                             corrupted and the if the Nack is for the PDU with set A flag it
                             should be retransmitted.*/
                            break;
                        case 3:
                            /* NAck.REASON = Transport-payload not supported
                             Supporting only types to 3 including ('Restart Message'), their
                             implementation is necessary. Do not pay attention to that Nack!*/
                            break;
                        case 4:
                            /* NAck.REASON = Static-payload type not supported
                             the NAck is of interest only if it is a static type == 0 => (H.225) payload!*/
                            if (AsNAckReason4( pReason )[IAnnexENAckReason4_STATIC_TYPE] == 0) {
                                static_type0_is_not_supported( pNode );
                            }
                            break;
                        case 5:
                            /* NAck.REASON = OID-payload not supported
                               Do not pay attention to that Nack!*/
                            break;
                        case 6:
                            /* NAck.REASON = Payload Corrupted
                             The NAck is of interest only if it is about a PDU waiting for pWaitingForAckPDU!*/
                            if (!fResendForced && (pNode->pWaitingForAckPDU != NULL) && (reason_seqn == ntoh24( &pNode->pWaitingForAckPDU->PDU[IAnnexEHeader_SEQN] ))) {
                                fResendForced = TRUE;
                                stop_retransmit_or_ima_timer( pNode );
                                pNode->nRetry--;
                                retransmit_or_ima_timer_event( pNode );
                            }
                        default:
                            /* reserved for future use => skipped! */
                            break;
                        }

                        /* goto next reason */
                        pReason = MoveToNextReason( pReason, nSz );
                    }
                    pPayload = (IAnnexEPayloadHeader*)pReason;
                }
                break;
            case AEPT00_Restart:
                /*  check size of payload! */
                nSz = sizeof_IAnnexET00Restart;
                nBytesAvail -= nSz;
                if (nBytesAvail < 0) {
                    /* incorrect payload size! payload corrupted! */
                    send_nack6( pNode, seqn, nCurPayload, TRUE );
                    fError = TRUE;
                    break;
                }
                /* notify application!*/
                if (pNode->pAnnexE->events.AnnexEEvRestart != NULL) {
                    cmTransportAddress SrcAddr;
                    SrcAddr.distribution    = cmDistributionUnicast;
                    SrcAddr.type            = cmTransportTypeIP;
                    SrcAddr.ip              = pNode->RemoteHost.nIP;
                    SrcAddr.port            = pNode->RemoteHost.nPort;
                    pNode->pAnnexE->events.AnnexEEvRestart(
                            AsHANNEXE( pNode->pAnnexE ),
                            pNode->pAnnexE->hAppAnnexE,
                            &SrcAddr
                        );
                }
                else
                {
                    msaPrintFormat( pNode->pAnnexE->msaType,
                                    "Restart command arrived - no CB to treat it was given");

                }
                pPayload = MoveToNextPayload( pPayload, nSz );
                break;
            default:
                {
                    int transType = pTrPayload[IAnnexET00Header_TRANSPORT_TYPE];
                    /* reserved for future use.... (not supported by this version of AnnexE)*/
                    send_nack3( pNode, seqn, transType, TRUE );

                    /* break the processing of the rest payloads in the PDU as there
                    is no guarantee to find the exact size of the payload.*/
                    fError = TRUE;
                }
                break;
            }
        };
        break;
        case AEPT_OIDTypedMessage: {
            /***************************************************************/
            /* T == 01 * OBJECT IDENTIFIER typed messages                  */
            /***************************************************************/
            int iLength;

            /*  check size of payload! */
            if ((int)sizeof_OIDHeader( pPayload ) >= nBytesAvail) {
                /*  incorrect payload size! payload corrupted! */
                send_nack6( pNode, seqn, nCurPayload, TRUE );
                fError = TRUE;
                break;
            }
            nSz = sizeof_OID( pPayload );
            nBytesAvail -= nSz;
            if (nBytesAvail < 0) {
                /* incorrect payload size! payload corrupted! */
                send_nack6( pNode, seqn, nCurPayload, TRUE );
                fError = TRUE;
                break;
            }

            /* that type of messages is not supported in the current implementation of
            the Annex E => return corresponding NAck (REASON_5: "Object-ID payload
            not supported)! As it is possible to find the exact size of the payload
            the PDU parsing is not broken, but the current payload is skipped!*/
            iLength = AsOIDHeader(pPayload)[IAnnexET01Header_OID_LENGTH];
            send_nack5( pNode,
                        seqn,
                        iLength,
                        &AsOIDHeader(pPayload)[IAnnexET01Header_OID],
                        FALSE );

            pPayload = MoveToNextPayload( pPayload, sizeof_OID( pPayload ) );
        };
        break;
        case AEPT_StaticMessage: {
            /***************************************************************/
            /* T == 10 * Static-payload typed messages                     */
            /***************************************************************/

            /* typecast to the Annex E Static-typed message payload */
            IAnnexET10Payload*  pStPayload = (IAnnexET10Payload*)pPayload;

            BOOL                fSessionField = pStPayload[IAnnexET10Payload_Header+IAnnexET10Header_PFLAGS] & AEP_MASK_S;
            BOOL                fAddressField = pStPayload[IAnnexET10Payload_Header+IAnnexET10Header_PFLAGS] & AEP_MASK_A;
            UINT16              nSessionID;
            UINT32              nAddress = 0;
            BYTE*               pData;
            UINT16              nDataSize;
            int                 staticType;
            int                 iMsgSize;

            /*  check size of payload! */
            nSz = sizeof_Static(pPayload);
            nBytesAvail -= nSz;
            if (nBytesAvail < 0) {
                /*  incorrect payload size! payload corrupted! */
                send_nack6( pNode, seqn, nCurPayload, TRUE );
                fError = TRUE;
                break;
            }

            if (pStPayload[IAnnexET10Payload_Header+IAnnexET10Header_STATIC_TYPE] != 0) {
                /* this implementation of the Annex E supports only H.225 messages,
                 all the rest are unknown currently.*/
                staticType = pStPayload[IAnnexET10Payload_Header+IAnnexET10Header_STATIC_TYPE];
                send_nack4( pNode, seqn, staticType, FALSE );

                /* skip payload*/
                pPayload = MoveToNextPayload( pPayload, sizeof_Static(pStPayload) );
                break;
            }

            if (fSessionField) {
                if (fAddressField) {
                    nSessionID = ntoh16( &AsStaticSA(pStPayload)[IAnnexET10PayloadSA_SESSION] );
                    nAddress = ntoh32( &AsStaticSA(pStPayload)[IAnnexET10PayloadSA_SESSION] );
                    pData = &AsStaticSA(pStPayload)[IAnnexET10PayloadSA_DATA];
                    nDataSize = ntoh16( &AsStaticSA(pStPayload)[IAnnexET10PayloadSA_DATA_LENGTH] );
                }
                else {
                    nSessionID = ntoh16( &AsStaticS(pStPayload)[IAnnexET10PayloadS_SESSION] );
                    pData = &AsStaticS(pStPayload)[IAnnexET10PayloadS_DATA];
                    nDataSize = ntoh16( &AsStaticS(pStPayload)[IAnnexET10PayloadS_DATA_LENGTH] );
                }

                /* Turn the last bit of the session Id for incoming msgs */
                nSessionID ^= 0x8000U;
            }
            else {
                /* this h.225 message has no session fields defined. From AnnexE API those
                messages are only session oriented => we suppose the payload is
                broken while transferring.*/
                send_nack6( pNode, seqn, nCurPayload, FALSE );

                /* Do not break the processing of the PDU as that mistake may be in
                result of a bug in the remote Annex E module implementation. It is
                possible to follow valid payloads in the PDU!

                skip payload*/
                pPayload = MoveToNextPayload( pPayload, sizeof_Static(pStPayload) );
                break;
            }

            /* everything is alright and we may notify the user for the received payload*/
            if (pNode->pAnnexE->events.AnnexEEvNewMessage != NULL) {
                pNode->fDontSend = TRUE; /* block sends until all the treatment is done by the user */
                pNode->nRef++; /* protect the node*/
                iMsgSize = nDataSize;
                pNode->pAnnexE->events.AnnexEEvNewMessage(
                        AsHANNEXE( pNode->pAnnexE ),
                        pNode->pAnnexE->hAppAnnexE,
                        pNode->RemoteHost.nIP,
                        pNode->RemoteHost.nPort,
                        pData,
                        iMsgSize
                    );
                if (pNode->nRef == 1) {
                    /* node is closed by the application ?!?!*/
                    del_node( pNode );
                }
                else
                {
                    pNode->nRef--; /* unprotect the nodee*/
                    pNode->fDontSend = FALSE; /* allow sends again */

                    /* send any messages that the user has sent during the callback */
                    if (pNode->pCurrentPDU)
                        send_current_pdu( pNode );
                }
            }

            /* static-payload processing is done! now skip to the next one!*/
            pPayload = MoveToNextPayload( pPayload, nSz );
        };
        break;
        case AEPT_ReservedForFutureUse: {
            /***************************************************************/
            /* T == 11 * Reserved for future use                           */
            /***************************************************************/

            /* this is not a valid Annex E Transport message!*/
            send_nack6( pNode, seqn, nCurPayload, TRUE );

            /* break the processing of the rest payloads in the PDU as there is no
             guarantee to find the exact size of the payload.*/
            fError = TRUE;
        };
        break;
        }

        if (fError) {
            /* during the parsing of the current payload in the PDU there
            was a serious error! => break further processing!*/
            break;
        }

        nCurPayload++;
    }

    if ((!fError) && (AEHGet_A( pPDU->PDU ) != 0) && (AEHGet_H( pPDU->PDU ) == 0) && (pNode->pCurrentPDU != NULL)) {
        /* send current pdu forced*/
        send_current_pdu( pNode );
    }
}