Newer
Older
#include "packet_interface.h"
/************* Functions definition *************/
pkt_t* pkt_new()
{
Vany Ingenzi
a validé
pkt_t * toReturn = (pkt_t *) calloc(1, sizeof(pkt_t));
}
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)
return E_TR;
if (len < ACK_OR_NACK_HEADER_SIZE)
return E_NOHEADER;
if (len > ACK_OR_NACK_HEADER_SIZE)
@brief : We don't check the checksum and the window here
**/
uint32_t crc1;
memcpy((void *) &crc1, &data[6], 4);
crc1 = ntohl(crc1);
if ( calculate_crc(data, 6) != crc1 )
return E_CRC;
const uint32_t timestamp;
memcpy((void *) ×tamp, &data[2], 4);
// Copy the information to pkt
memcpy(&(pkt->header.front), 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)
{
memcpy((void *) &length, (void *) &data[1], 2);
if ( len < PKT_MIN_HEADERLEN )
return E_NOHEADER;
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) )
// 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;
memcpy((void *) &crc1, (void *) &data[8], 4);
if ( calculate_crc(modified_header, 8) != crc1 )
const uint8_t seqnum = (uint8_t) data[3];
@brief : We don't check the checksum and the window here
**/
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;
pkt_set_crc2(pkt, crc2);
uint32_t timestamp;
memcpy((void *) ×tamp, &data[4], 4);
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);
}
pkt_status_code pkt_decode(const char *data, const size_t len, pkt_t *pkt)
{
ptypes_t type = ((data[0]) & TYPE_MASK) >> TYPE_SHIFT;
return pkt_decode_ack_nack(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;
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 *) ×tamp, 4);
uint32_t crc1 = htonl(calculate_crc(buf, 6));
memcpy((void *) &buf[6], (void *) &crc1, CRC_SIZE);
*len = ACK_OR_NACK_HEADER_SIZE;
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 *) ×tamp, 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);
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);
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)
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);
}
const char* pkt_get_payload(const pkt_t* pkt)
{
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);
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_status_code pkt_set_crc2(pkt_t *pkt, const uint32_t crc2)
{
}
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;
if (type != PTYPE_DATA && type != PTYPE_FEC) {
size -= sizeof(pkt->header.length);
}
return size;