Skip to content
Extraits de code Groupes Projets
packet_interface.c 8,01 ko
Newer Older
  • Learn to ignore specific revisions
  • #include "packet_interface.h"
    
    
    /************* Functions definition *************/
    pkt_t* pkt_new()
    {
    
        pkt_t * toReturn = (pkt_t *) calloc(1, sizeof(pkt_t));
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        return  toReturn;
    
    }
    
    void pkt_del(pkt_t *pkt)
    {
        free(pkt);
    }
    
    
    uint32_t calculate_crc(const char * buffer, uint32_t len)
    
        return (uint32_t) crc32(0L, (const void *) buffer, len);
    
    pkt_status_code pkt_decode_ack_nack(const char *data, const size_t len, pkt_t *pkt)
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        if ((data[0] & TR_MASK) != 0)
    
            return E_TR;
    
        if (len < ACK_OR_NACK_HEADER_SIZE)
            return E_NOHEADER;
    
        if (len > ACK_OR_NACK_HEADER_SIZE) 
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
            return E_UNCONSISTENT;
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        @brief : We don't check the checksum and the window here
        **/
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
    
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        // CRC no need to set TR at 0 as it should be at 0
    
        uint32_t crc1;
        memcpy((void *) &crc1, &data[6], 4);
        crc1 = ntohl(crc1);
        if ( calculate_crc(data, 6) != crc1 )
            return E_CRC; 
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
    
    
        const uint32_t timestamp;
        memcpy((void *) &timestamp, &data[2], 4);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
    
    
        // Copy the information to pkt
        memcpy(&(pkt->header.front), data, 1);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        const uint8_t seqnum = (uint8_t) data[1];
    
        pkt_set_seqnum(pkt, seqnum);
        pkt_set_timestamp(pkt, timestamp);
        pkt_set_crc1(pkt, crc1);
    
        return PKT_OK;
    }
    
    pkt_status_code pkt_decode_data_fec(const char *data, const size_t len, pkt_t *pkt)
    {
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        uint16_t length;
    
        memcpy((void *) &length, (void *) &data[1], 2);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        length = ntohs(length);
    
    
        if ( len < PKT_MIN_HEADERLEN )
            return E_NOHEADER;
    
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        if ( len > PKT_MAX_LEN || length > MAX_PAYLOAD_SIZE )
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
            return E_LENGTH;
    
    
        ptypes_t type = (data[0] & TYPE_MASK) >> TYPE_SHIFT; 
        if ( type == PTYPE_FEC  && (data[0] & TR_MASK ) != 0 )
            return E_TR;
    
    
        if ( len != (sizeof(header_t) + TIMESTAMP_SIZE + CRC_SIZE + length + CRC_SIZE) )
    
            return E_UNCONSISTENT; 
    
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        // We set the TR to 0 in order to calculcate the CRC on the header
    
        char modified_header[8]; 
        memcpy((void *) &modified_header, (void *) data, 8);
        modified_header[0] = modified_header[0] & TR_SETTER_TO_ZERO; 
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
    
        uint32_t crc1;
    
        memcpy((void *) &crc1, (void *) &data[8], 4);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        crc1 = ntohl((uint32_t) crc1);
    
        if ( calculate_crc(modified_header, 8) != crc1 )
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
            return E_CRC; 
    
    
        const uint8_t seqnum = (uint8_t) data[3];
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        @brief : We don't check the checksum and the window here
        **/
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        uint32_t crc2;
    
        if ( (type == PTYPE_DATA && (data[0] & TR_MASK ) != 0) || type == PTYPE_FEC )
    
        {
            memcpy((void *) &crc2, &data[12+length], 4);
            crc2 = ntohl((uint32_t) crc2);
            if (calculate_crc(&data[12], length) != crc2)
                return E_CRC;
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
    
    
        uint32_t timestamp;
        memcpy((void *) &timestamp, &data[4], 4);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
    
        memcpy(&(pkt->header.front), data, 1);
    
        pkt_set_length(pkt, length);
        pkt_set_seqnum(pkt, seqnum);
        pkt_set_timestamp(pkt, timestamp);
        pkt_set_crc1(pkt, crc1);
        pkt_set_payload(pkt, &data[12], length);
    
        return PKT_OK;
    
    }
    
    pkt_status_code pkt_decode(const char *data, const size_t len, pkt_t *pkt)
    {
    
        ptypes_t type = ((data[0]) & TYPE_MASK) >> TYPE_SHIFT; 
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        if ( type == PTYPE_ACK || type == PTYPE_NACK)
    
            return pkt_decode_ack_nack(data, len, pkt);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        } else
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
            return pkt_decode_data_fec(data, len, pkt); 
        }  
    
    pkt_status_code pkt_encode_ACK_NACK(const pkt_t *pkt, char *buf, size_t *len)
    
        size_t required = ACK_OR_NACK_HEADER_SIZE;
    
        if (*len < required)
            return E_NOMEM;
    
        memcpy((void *) &buf[0], (void *) &(pkt->header.front),   1);
        memcpy((void *) &buf[1], (void *) &(pkt->header.seqnum),  1);
        uint32_t timestamp = pkt_get_timestamp(pkt);
        memcpy((void *) &buf[2], (void *) &timestamp,             4);
        uint32_t crc1      = htonl(calculate_crc(buf, 6));
        memcpy((void *) &buf[6], (void *) &crc1,           CRC_SIZE);
        *len = ACK_OR_NACK_HEADER_SIZE;
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        return PKT_OK;
    
    pkt_status_code pkt_encode_DATA_FEC(const pkt_t *pkt, char *buf, size_t *len)
    
    {   
        // Let's first copy the header
        if ( *len < 12 ) return E_NOMEM;
        memcpy((void *) &buf[0],   (void *) &(pkt->header.front),   1);
        uint16_t n_length  = htons(pkt_get_length(pkt));
        memcpy((void *) &buf[1], (void *) &n_length,                2);
        memcpy((void *) &buf[3], (void *) &(pkt->header.seqnum),    1);
        uint32_t timestamp = pkt_get_timestamp(pkt);
        memcpy((void *) &buf[4], (void *) &timestamp,               4);
        uint32_t crc1      = htonl(calculate_crc(buf, 8));
        memcpy((void *) &buf[8], (void *) &crc1, CRC_SIZE);
    
        size_t required_size;
        ptypes_t type = pkt_get_type(pkt);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        uint16_t length = (type == PTYPE_DATA && pkt_get_tr(pkt) == 0) ?  pkt_get_length(pkt) : MAX_PAYLOAD_SIZE;
        required_size = sizeof(header_t) + TIMESTAMP_SIZE + CRC_SIZE + length + CRC_SIZE;
        if ( *len < required_size ) 
            return E_NOMEM;
    
        memcpy((void *) &buf[12], (void *) pkt->payload, length);
        uint32_t crc2 = htonl(calculate_crc(&buf[12], length));
        memcpy((void *) &buf[12 + length], (void *) &crc2, CRC_SIZE);
        *len =  sizeof(header_t) + TIMESTAMP_SIZE + CRC_SIZE + length + CRC_SIZE;
    
        return PKT_OK;
    }
    
    pkt_status_code pkt_encode(const pkt_t *pkt, char *buf, size_t *len)
    {
        ptypes_t type = pkt_get_type(pkt);
        if      ( type == PTYPE_ACK  || type == PTYPE_NACK )
    
        {
            return pkt_encode_ACK_NACK(pkt, buf, len); 
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        } else if ( type == PTYPE_DATA || type == PTYPE_FEC) 
    
            return pkt_encode_DATA_FEC(pkt, buf, len);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        } else 
    
            return E_UNCONSISTENT;
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
    
    
    /** GETTER */
    
    ptypes_t pkt_get_type(const pkt_t* pkt)
    
        return (pkt->header.front & TYPE_MASK) >> TYPE_SHIFT;
    
    }
    
    uint8_t  pkt_get_tr(const pkt_t* pkt)
    {
    
        return (pkt->header.front & TR_MASK) >> TR_SHIFT;
    
    }
    
    uint8_t  pkt_get_window(const pkt_t* pkt)
    {
    
        return pkt->header.front & WINDOW_MASK;
    
    }
    
    uint8_t  pkt_get_seqnum(const pkt_t* pkt)
    {
    
        return pkt->header.seqnum;
    
    }
    
    uint16_t pkt_get_length(const pkt_t* pkt)
    {
    
        return ntohs(pkt->header.length);
    
    // No problem with endianess here !
    
    uint32_t pkt_get_timestamp(const pkt_t* pkt)
    
        return pkt->timestamp;
    
    uint32_t pkt_get_crc1(const pkt_t* pkt)
    
        return ntohl(pkt->crc1);
    
    uint32_t pkt_get_crc2(const pkt_t* pkt)
    
    {   
        ptypes_t type = pkt_get_type(pkt);
        uint8_t  tr   = pkt_get_tr(pkt);
        if ( type == PTYPE_FEC || (type == PTYPE_DATA && tr == 0) )
        {
            return ntohl(pkt->crc2);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        } else      // There is no crc2
    
    }
    
    const char* pkt_get_payload(const pkt_t* pkt)
    {
    
        return (const char *) pkt->payload;
    
    pkt_status_code pkt_set_type(pkt_t *pkt, const ptypes_t type)
    {
    
        pkt->header.front |= (type << TYPE_SHIFT);
        return PKT_OK;
    
    }
    
    pkt_status_code pkt_set_tr(pkt_t *pkt, const uint8_t tr)
    {
    
        pkt->header.front |= (tr << TR_SHIFT);
        return PKT_OK;
    
    }
    
    pkt_status_code pkt_set_window(pkt_t *pkt, const uint8_t window)
    {
    
        pkt->header.front |= window;
        return PKT_OK;
    
    }
    
    pkt_status_code pkt_set_seqnum(pkt_t *pkt, const uint8_t seqnum)
    {
    
        pkt->header.seqnum = seqnum;
        return PKT_OK;
    
    }
    
    pkt_status_code pkt_set_length(pkt_t *pkt, const uint16_t length)
    {
    
        pkt->header.length = htons(length);
    
        return PKT_OK;
    
    // No problem with endianess here !
    
    pkt_status_code pkt_set_timestamp(pkt_t *pkt, const uint32_t timestamp)
    {
    
        pkt->timestamp = timestamp;
        return PKT_OK;
    
    }
    
    pkt_status_code pkt_set_crc1(pkt_t *pkt, const uint32_t crc1)
    {
    
        pkt->crc1 = htonl(crc1);
    
        return PKT_OK;
    
    }
    
    pkt_status_code pkt_set_crc2(pkt_t *pkt, const uint32_t crc2)
    {
    
        pkt->crc2 = htonl(crc2);  
    
        return PKT_OK;
    
    }
    
    pkt_status_code pkt_set_payload(pkt_t *pkt,
                                    const char *data,
                                    const uint16_t length)
    {
    
        if (length > MAX_PAYLOAD_SIZE) 
            return E_NOMEM;
        memcpy(pkt->payload, data, length);
        return PKT_OK;
    
    }
    
    
    ssize_t predict_header_length(const pkt_t *pkt)
    {
    
        ssize_t size  = sizeof(header_t) + TIMESTAMP_SIZE;
    
        ptypes_t type = pkt_get_type(pkt);
    
        if (type != PTYPE_DATA && type != PTYPE_FEC) {
    
            size -= sizeof(pkt->header.length);
        }
        return size;