Example #1
0
static void handle_ack (int sock, char * packet, int psize, int hsize)
{
  struct allnet_header * hp = (struct allnet_header *) packet;
  /* save the acks */
  char * ack = packet + ALLNET_SIZE (hp->transport);
  int count = (psize - hsize) / MESSAGE_ID_SIZE; 
  int i;
  for (i = 0; i < count; i++) {
    char * peer;
    keyset kset;
    long long int ack_number = ack_received (ack, &peer, &kset);
    if (ack_number > 0) {
#ifdef DEBUG_PRINT
      printf ("sequence number %lld acked\n", ack_number);
#endif /* DEBUG_PRINT */
      request_and_resend (sock, peer, kset);
/*    } else if (ack_number == -2) {
      printf ("packet acked again\n"); */
    } else if (is_recently_sent_ack (ack)) {
      /* printf ("received my own ack\n"); */
    } else {
      /* print_buffer (ack, MESSAGE_ID_SIZE, "unknown ack rcvd",
                    MESSAGE_ID_SIZE, 1); */
    }
    fflush (NULL);
/* */
    ack += MESSAGE_ID_SIZE;
  }
}
Example #2
0
void
MulticastDataLink::sample_received(ReceivedDataSample& sample)
{
  switch (sample.header_.message_id_) {
  case TRANSPORT_CONTROL: {
    // Transport control samples are delivered to all sessions
    // regardless of association status:
    {
      ACE_GUARD(ACE_SYNCH_RECURSIVE_MUTEX,
                guard,
                this->session_lock_);

      char* ptr = sample.sample_->rd_ptr();
      for (MulticastSessionMap::iterator it(this->sessions_.begin());
          it != this->sessions_.end(); ++it) {
        it->second->control_received(sample.header_.submessage_id_,
                                    sample.sample_);
        // reset read pointer
        sample.sample_->rd_ptr(ptr);
      }
    }
    if (this->check_fully_association_) {
      this->transport_->check_fully_association ();
      this->check_fully_association_ = false;
    }
  } break;

  case SAMPLE_ACK:
    ack_received(sample);
    break;

  default:
    data_received(sample);
  }
}
Example #3
0
void
MulticastDataLink::sample_received(ReceivedDataSample& sample)
{
  switch (sample.header_.message_id_) {
  case TRANSPORT_CONTROL: {
    // Transport control samples are delivered to all sessions
    // regardless of association status:
    {
      char* const ptr = sample.sample_ ? sample.sample_->rd_ptr() : 0;

      ACE_GUARD(ACE_SYNCH_RECURSIVE_MUTEX,
          guard,
          this->session_lock_);

      const TransportHeader& theader = receive_strategy()->received_header();

      if (!is_active() && sample.header_.submessage_id_ == MULTICAST_SYN &&
          sessions_.find(theader.source_) == sessions_.end()) {
        // We have received a SYN but there is no session (yet) for this source.
        // Depending on the data, we may need to send SYNACK.

        guard.release();
        syn_received_no_session(theader.source_, sample.sample_,
            theader.swap_bytes());
        if (ptr) {
          sample.sample_->rd_ptr(ptr);
        }
        return;
      }

      MulticastSessionMap temp_sessions(sessions_);
      guard.release();

      for (MulticastSessionMap::iterator it(temp_sessions.begin());
          it != temp_sessions.end(); ++it) {
        it->second->control_received(sample.header_.submessage_id_,
            sample.sample_);
        // reset read pointer
        if (ptr) {
          sample.sample_->rd_ptr(ptr);
        }
      }
    }
  } break;

  case SAMPLE_ACK:
    ack_received(sample);
    break;

  default:
    if (!duplicate_data_sample(sample.header_)) {
      data_received(sample);
    }
    break;
  }
}
Example #4
0
static void datalink_up(CnetEvent ev, CnetTimerID timer, CnetData data)
{
    FRAME frame;
    int link, checksum;

    // READ PHYSICAL LAYER FRAME
    size_t frameLength = sizeof(FRAME);
    CHECK(CNET_read_physical(&link, (char *)&frame, &frameLength));

    // ENSURE CHECKSUM WAS OKAY
    checksum = frame.checksum;
    frame.checksum = 0;

    if (CNET_ccitt((unsigned char *)&frame, (int)frameLength) != checksum)
    {
        // CHECKSUM IS BAD SO DROP THE PACKET. SENDER WILL TIMEOUT + RESEND
        printf("\t\t\t\t\tFRAME RECEIVED\n\t\t\t\t\tBAD CHECKSUM - IGNORE\n");
        return;
    }

    if (frame.kind == DL_DATA)
    {
        // PRINT FULL INFO OF ALL DATA WITHIN THE FRAME
        printf("\n\t\t\t\t\tDATA RECEIVED\n");
        printf("\t\t\t\t\tSOURCE:\t%s\n", nodenames[frame.srcNode]);
        printf("\t\t\t\t\tDEST:\t%s\n", nodenames[frame.destNode]);
        printf("\t\t\t\t\tIN LINK:\t%d\n", link);
        printf("\t\t\t\t\tSEQ NO:\t%d\n", frame.seq);
        printf("\t\t\t\t\tDATA:\t%s\n", frame.data);
        printf("\t\t\t\t\tLENGTH:\t%d\n", frame.len);

        // CHECK IF SEQUENCE NUMBER OF FRAME IS THE ONE WE EXPECT
        if (frame.seq == frameExpected[link - 1])
        {
            // ACCEPT IT, THROW FRAME UP TO THE NETWORK LAYER
            network_up(frame, link);
        }
        // CHECK IF FRAME IS A DUPLICATE
        // MATHS CHECKS IF SEQ == FRAMEEXPECTED - 1, ACCOUNTING FOR WRAPAROUND
        else if (frame.seq == (frameExpected[link - 1] + MAX_SEQ) % (MAX_SEQ + 1))
        {
            printf("\t\t\t\t\tDUPLICATE FRAME\n");
            printf("\t\t\t\t\tEXPECTED: %d\n", frameExpected[ link - 1]);

            // DUPLICATE MUST BE BECAUSE ACK LOST, RESEND THE ACK
            transmit_ack(link, frame.seq);
        }
    }
    // IF NOT DATA, MUST BE AN ACK FRAME
    else
    {
        // DEAL WITH ACK VIA GO-BACK-N
        ack_received(frame, link);
    }
}
Example #5
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 );
    }
}