packet.c 18.6 KB
Newer Older
1 2 3 4
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
5
#include <netinet/in.h>
6 7
#include "../util/common.h"
#include "../util/dbg.h"
8
#include <stdbool.h>
9
#include <arpa/inet.h>
Andreas Schmidt's avatar
Andreas Schmidt committed
10
#include "packet.h"
11
#include "clock.h"
12

13
static void *encode_general_header(void *buf_ptr, const PrrtPacket *packet);
14

15
static void *encode_data_header(void *buf_ptr, const void *payload);
16

17
static void *encode_redundancy_header(void *buf_ptr, const void *payload);
18

19
static void *encode_feedback_header(void *buf_ptr, const void *payload);
20

21
static void *decode_data_header(void *dstBuffer, const void *srcBuffer);
Andreas Schmidt's avatar
Andreas Schmidt committed
22

23
static void *decode_redundancy_header(void *dstBuffer, const void *srcBuffer);
24

25
static void *decode_feedback_header(void *dstBuffer, const void *srcBuffer);
Andreas Schmidt's avatar
Andreas Schmidt committed
26

27
prrtPacketType_t PrrtPacket_type(PrrtPacket *packet_ptr) {
28
    return (prrtPacketType_t) ((packet_ptr->type_priority >> 4) & 0x0F);
29 30
}

31
uint8_t PrrtPacket_priority(PrrtPacket *packet_ptr) {
32 33 34
    return (uint8_t) (packet_ptr->type_priority & 0x0F);
}

35
prrtPacketLength_t PrrtPacket_size(PrrtPacket *packet_ptr) {
36
    return (prrtPacketLength_t) (packet_ptr->payloadLength + PRRT_PACKET_GENERAL_HEADER_SIZE);
37 38
}

39
int PrrtPacket_print(PrrtPacket *packet_ptr) {
40 41
    printf(" 0                   1                   2                   3\n"
                   " 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n"
42
                   "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
43
    prrtPacketType_t type = PrrtPacket_type(packet_ptr);
44

45
    printf("| %5u | %5u | %13u | %29u |\n", type, PrrtPacket_priority(packet_ptr), packet_ptr->index,
46
           packet_ptr->sequenceNumber);
47
    printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
48

49
    if (type == PACKET_TYPE_DATA) {
50
        PrrtPacketDataPayload *payload = packet_ptr->payload;
51 52
        printf("| %61u |\n", payload->timestamp);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
53
        printf("| %61u |\n", payload->groupRTprop_us);
54
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
55 56
        printf("| %61u |\n", payload->packetTimeout_us);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
57 58
        printf("| %61s |\n", (char *) (packet_ptr->payload + PRRT_PACKET_DATA_HEADER_SIZE));
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
59
    } else if (type == PACKET_TYPE_REDUNDANCY) {
60
        PrrtPacketRedundancyPayload *payload = packet_ptr->payload;
61
        printf("| %29u | %13u | %13u |\n", payload->baseSequenceNumber, payload->n, payload->k);
62
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
63
    } else if (type == PACKET_TYPE_FEEDBACK) {
64 65
        prrtPacketLength_t i = 0;

66
        PrrtPacketFeedbackPayload *payload = packet_ptr->payload;
67

68
        printf("| %61u |\n", payload->groupRTT_us);
69
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
70
        printf("| %61u |\n", payload->forwardTripTimestamp_us);
71
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
72
        printf("| %29u | %29u |\n", payload->erasureCount, payload->packetCount);
73
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
74
        printf("| %29u | %29u |\n", payload->gapLength, payload->gapCount);
75
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
76
        printf("| %29u | %29u |\n", payload->burstLength, payload->burstCount);
77
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
78 79 80 81 82

        prrtPacketLength_t remainingSpace = ((prrtPacketLength_t) (packet_ptr->payloadLength -
                                                                   PRRT_PACKET_FEEDBACK_HEADER_SIZE));
        prrtPacketLength_t blockCount = (prrtPacketLength_t) (remainingSpace / sizeof(PrrtIncompleteBlock));

83
        for (i = 0; i < blockCount; ++i) {
84 85 86 87
            PrrtIncompleteBlock block = payload->incompleteBlocks[i];
            printf("| %29u | %29u |\n", block.sequenceNumberBase, block.repairCycleIndex);
            printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
        }
88
    } else {
89 90
        printf("| Unhandeled Type                                               |\n");
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
91 92 93 94 95
    }

    return 0;
}

96
PrrtPacket *PrrtPacket_copy(PrrtPacket *original) {
97 98
    PrrtPacket *newPacket = calloc(1, sizeof(PrrtPacket));
    check_mem(newPacket);
99
    void *payload = calloc(1, original->payloadLength);
100 101 102
    check_mem(payload);

    newPacket->payload = payload;
103 104
    newPacket->payloadLength = original->payloadLength;
    memcpy(newPacket->payload, original->payload, original->payloadLength);
105 106

    newPacket->index = original->index;
107
    newPacket->sequenceNumber = original->sequenceNumber;
108 109 110 111 112
    newPacket->type_priority = original->type_priority;


    return newPacket;
    error:
113
    PERROR("Not enough memory for packet copies.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
114
    return NULL;
115 116
}

117 118
static PrrtPacket *
create_header(uint8_t priority, prrtSequenceNumber_t seqno, prrtPacketLength_t size, uint8_t type, uint8_t index) {
Andreas Schmidt's avatar
Andreas Schmidt committed
119 120 121 122 123 124
    PrrtPacket *packet = calloc(1, sizeof(PrrtPacket));
    check_mem(packet);

    packet->type_priority = type << 4;
    packet->type_priority |= priority & 0x0F;
    packet->index = index;
125 126
    packet->sequenceNumber = seqno;
    packet->payloadLength = size;
Andreas Schmidt's avatar
Andreas Schmidt committed
127 128 129 130 131

    return packet;

    error:
    PERROR("Could not create packet.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
132
    return NULL;
Andreas Schmidt's avatar
Andreas Schmidt committed
133 134
}

135
bool PrrtPacket_encode(void *buf_ptr, uint16_t buf_size, PrrtPacket *packet_ptr) {
136
    void *payload = packet_ptr->payload;
137

138
    check(packet_ptr->payloadLength + PRRT_PACKET_GENERAL_HEADER_SIZE <= buf_size, "Buffer too small.");
139

140 141
    buf_ptr = encode_general_header(buf_ptr, packet_ptr);

142
    prrtPacketType_t type = PrrtPacket_type(packet_ptr);
143
    if (type == PACKET_TYPE_DATA) {
144
        buf_ptr = encode_data_header(buf_ptr, payload);
145
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_DATA_HEADER_SIZE);
146
    } else if (type == PACKET_TYPE_REDUNDANCY) {
147
        buf_ptr = encode_redundancy_header(buf_ptr, payload);
148
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
149
    } else if (type == PACKET_TYPE_FEEDBACK) {
150
        encode_feedback_header(buf_ptr, payload);
151 152
    } else {
        perror("NOT IMPLEMENTED");
153
        return false;
154
    }
155
    return true;
156 157

    error:
158
    return false;
159 160
}

161
void *encode_redundancy_header(void *buf_ptr, const void *payload) {
162
    const PrrtPacketRedundancyPayload *redundancyPayload = payload;
163

164 165 166
    prrtSequenceNumber_t *baseSeqNo = (prrtSequenceNumber_t *) buf_ptr;
    *baseSeqNo = htons(redundancyPayload->baseSequenceNumber);
    buf_ptr += sizeof(prrtSequenceNumber_t);
167 168 169

    uint8_t *n = (uint8_t *) buf_ptr;
    *n = redundancyPayload->n;
170
    buf_ptr += sizeof(uint8_t);
171 172 173

    uint8_t *k = (uint8_t *) buf_ptr;
    *k = redundancyPayload->k;
174
    buf_ptr += sizeof(uint8_t);
175 176 177 178

    return buf_ptr;
}

179
void *encode_feedback_header(void *buf_ptr, const void *payload) {
180
    const PrrtPacketFeedbackPayload *feedbackPayload = payload;
181

182 183 184
    prrtTimedelta_t *groupRoundTripTime = (prrtTimedelta_t *) buf_ptr;
    *groupRoundTripTime = htonl(feedbackPayload->groupRTT_us);
    buf_ptr += sizeof(prrtTimedelta_t);
185

186 187 188
    prrtTimestamp_t *forwardTripTimestamp = (prrtTimestamp_t *) buf_ptr;
    *forwardTripTimestamp = htonl(feedbackPayload->forwardTripTimestamp_us);
    buf_ptr += sizeof(prrtTimestamp_t);
189

190 191 192
    prrtSequenceNumber_t *erasureCount = (prrtSequenceNumber_t *) buf_ptr;
    *erasureCount = htons(feedbackPayload->erasureCount);
    buf_ptr += sizeof(prrtSequenceNumber_t);
193

194 195 196
    prrtSequenceNumber_t *packetCount = (prrtSequenceNumber_t *) buf_ptr;
    *packetCount = htons(feedbackPayload->packetCount);
    buf_ptr += sizeof(prrtSequenceNumber_t);
197

198 199 200
    prrtSequenceNumber_t *gap = (prrtSequenceNumber_t *) buf_ptr;
    *gap = htons(feedbackPayload->gapLength);
    buf_ptr += sizeof(prrtSequenceNumber_t);
201

202 203 204
    prrtSequenceNumber_t *ngap = (prrtSequenceNumber_t *) buf_ptr;
    *ngap = htons(feedbackPayload->gapCount);
    buf_ptr += sizeof(prrtSequenceNumber_t);
205

206 207 208
    prrtSequenceNumber_t *burstLength = (prrtSequenceNumber_t *) buf_ptr;
    *burstLength = htons(feedbackPayload->burstLength);
    buf_ptr += sizeof(prrtSequenceNumber_t);
209

210 211 212
    prrtSequenceNumber_t *burstCount = (prrtSequenceNumber_t *) buf_ptr;
    *burstCount = htons(feedbackPayload->burstCount);
    buf_ptr += sizeof(prrtSequenceNumber_t);
213

214
    // TODO: encode variable number of incomplete blocks
215 216 217
    return buf_ptr;
}

218
void *encode_data_header(void *buf_ptr, const void *payload) {
219
    const PrrtPacketDataPayload *data_payload = payload;
220

221
    prrtPacketLength_t *packetLength = (prrtPacketLength_t *) buf_ptr;
rna's avatar
rna committed
222 223 224
    *packetLength = htonl(data_payload->dataLength);
    buf_ptr += sizeof(prrtPacketLength_t);

225
    prrtTimestamp_t *timestamp = (prrtTimestamp_t *) buf_ptr;
226
    *timestamp = htonl(data_payload->timestamp);
227
    buf_ptr += sizeof(prrtTimestamp_t);
228

229
    prrtTimedelta_t *group_round_trip_time = (prrtTimedelta_t *) buf_ptr;
230
    *group_round_trip_time = htonl(data_payload->groupRTprop_us);
231
    buf_ptr += sizeof(prrtTimedelta_t);
232

233 234 235
    prrtTimedelta_t *packet_timeout = (prrtTimedelta_t *) buf_ptr;
    *packet_timeout = htonl(data_payload->packetTimeout_us);
    buf_ptr += sizeof(prrtTimedelta_t);
236 237 238 239

    return buf_ptr;
}

240
void *encode_general_header(void *buf_ptr, const PrrtPacket *packet) {
241
    uint8_t *type_priority = (uint8_t *) buf_ptr;
242
    *type_priority = packet->type_priority;
243
    buf_ptr += sizeof(uint8_t);
244

245
    uint8_t *index = (uint8_t *) buf_ptr;
246
    *index = packet->index;
247
    buf_ptr += sizeof(uint8_t);
248

249 250 251
    prrtSequenceNumber_t *seqno = (prrtSequenceNumber_t *) buf_ptr;
    *seqno = htons(packet->sequenceNumber);
    buf_ptr += sizeof(prrtSequenceNumber_t);
252

253
    return buf_ptr;
254 255
}

256
bool PrrtPacket_decode(void *srcBuffer, uint16_t srcBufferSize, PrrtPacket *targetPacket) {
257
    prrtPacketLength_t payload_len = (prrtPacketLength_t) (srcBufferSize - PRRT_PACKET_GENERAL_HEADER_SIZE);
Andreas Schmidt's avatar
Andreas Schmidt committed
258 259 260 261 262
    targetPacket->type_priority = *(uint8_t *) srcBuffer;
    srcBuffer += 1;
    uint8_t *index_ptr = (uint8_t *) srcBuffer;
    targetPacket->index = *index_ptr;
    srcBuffer += 1;
263 264 265
    prrtSequenceNumber_t *seqno_prt = (prrtSequenceNumber_t *) srcBuffer;
    targetPacket->sequenceNumber = ntohs(*seqno_prt);
    srcBuffer += sizeof(prrtSequenceNumber_t);
266

Andreas Schmidt's avatar
Andreas Schmidt committed
267
    void *payload_buffer = calloc(1, payload_len);
268 269
    check_mem(payload_buffer);

Andreas Schmidt's avatar
Andreas Schmidt committed
270
    targetPacket->payload = payload_buffer;
271
    targetPacket->payloadLength = payload_len;
Andreas Schmidt's avatar
Andreas Schmidt committed
272

273
    prrtPacketType_t packetType = PrrtPacket_type(targetPacket);
274
    if (packetType == PACKET_TYPE_DATA) {
Andreas Schmidt's avatar
Andreas Schmidt committed
275 276
        srcBuffer = decode_data_header(srcBuffer, payload_buffer);
        PrrtPacket_copy_buffer_to_payload(targetPacket, srcBuffer, PRRT_PACKET_DATA_HEADER_SIZE);
277
    } else if (packetType == PACKET_TYPE_REDUNDANCY) {
Andreas Schmidt's avatar
Andreas Schmidt committed
278 279
        srcBuffer = decode_redundancy_header(srcBuffer, payload_buffer);
        PrrtPacket_copy_buffer_to_payload(targetPacket, srcBuffer, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
280
    } else if (packetType == PACKET_TYPE_FEEDBACK) {
281
        decode_feedback_header(srcBuffer, payload_buffer);
Andreas Schmidt's avatar
Andreas Schmidt committed
282
    } else {
283
        printf("NOT IMPLEMENTED\n");
Andreas Schmidt's avatar
Andreas Schmidt committed
284
    }
285
    return true;
286 287

    error:
288
    return false;
Andreas Schmidt's avatar
Andreas Schmidt committed
289
}
290

291
void *decode_redundancy_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
292
    PrrtPacketRedundancyPayload *redundancyPayload = (PrrtPacketRedundancyPayload *) srcBuffer;
293

294 295 296
    prrtSequenceNumber_t *baseSeqNo = (prrtSequenceNumber_t *) dstBuffer;
    redundancyPayload->baseSequenceNumber = ntohs(*baseSeqNo);
    dstBuffer += sizeof(prrtSequenceNumber_t);
297

Andreas Schmidt's avatar
Andreas Schmidt committed
298
    uint8_t *n = (uint8_t *) dstBuffer;
299
    redundancyPayload->n = *n;
300
    dstBuffer += sizeof(uint8_t);
301

Andreas Schmidt's avatar
Andreas Schmidt committed
302
    uint8_t *k = (uint8_t *) dstBuffer;
303
    redundancyPayload->k = *k;
304
    dstBuffer += sizeof(uint8_t);
305

Andreas Schmidt's avatar
Andreas Schmidt committed
306
    return dstBuffer;
307 308
}

309
void *decode_feedback_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
310
    PrrtPacketFeedbackPayload *feedback_payload = (PrrtPacketFeedbackPayload *) srcBuffer;
311

312 313 314
    prrtTimedelta_t *groupRoundTripTime = (prrtTimedelta_t *) dstBuffer;
    feedback_payload->groupRTT_us = ntohl(*groupRoundTripTime);
    dstBuffer += sizeof(prrtTimedelta_t);
315

316 317 318
    prrtTimestamp_t *forwardTripTime = (prrtTimestamp_t *) dstBuffer;
    feedback_payload->forwardTripTimestamp_us = ntohl(*forwardTripTime);
    dstBuffer += sizeof(prrtTimestamp_t);
319

320 321 322
    prrtSequenceNumber_t *erasureCount = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->erasureCount = ntohs(*erasureCount);
    dstBuffer += sizeof(prrtSequenceNumber_t);
323

324 325 326
    prrtSequenceNumber_t *packetCount = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->packetCount = ntohs(*packetCount);
    dstBuffer += sizeof(prrtSequenceNumber_t);
327

328 329 330
    prrtSequenceNumber_t *gap = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->gapLength = ntohs(*gap);
    dstBuffer += sizeof(prrtSequenceNumber_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
331

332 333 334
    prrtSequenceNumber_t *ngap = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->gapCount = ntohs(*ngap);
    dstBuffer += sizeof(prrtSequenceNumber_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
335

336 337 338
    prrtSequenceNumber_t *burst = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->burstLength = ntohs(*burst);
    dstBuffer += sizeof(prrtSequenceNumber_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
339

340 341 342
    prrtSequenceNumber_t *nburst = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->burstCount = ntohs(*nburst);
    dstBuffer += sizeof(prrtSequenceNumber_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
343

344
    // TODO: decode variable number of incomplete blocks
Andreas Schmidt's avatar
Andreas Schmidt committed
345
    return dstBuffer;
Andreas Schmidt's avatar
Andreas Schmidt committed
346 347
}

348
void *decode_data_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
349
    PrrtPacketDataPayload *data_payload = (PrrtPacketDataPayload *) srcBuffer;
Andreas Schmidt's avatar
Andreas Schmidt committed
350

rna's avatar
rna committed
351 352 353 354
    prrtPacketLength_t *dataLength = (prrtPacketLength_t *) dstBuffer;
    data_payload->dataLength = ntohl(*dataLength);
    dstBuffer += sizeof(prrtPacketLength_t);

355
    prrtTimestamp_t *timestamp = (prrtTimestamp_t *) dstBuffer;
Andreas Schmidt's avatar
Andreas Schmidt committed
356
    data_payload->timestamp = ntohl(*timestamp);
357
    dstBuffer += sizeof(prrtTimestamp_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
358

359
    prrtTimedelta_t *group_round_trip_time = (prrtTimedelta_t *) dstBuffer;
360
    data_payload->groupRTprop_us = ntohl(*group_round_trip_time);
361
    dstBuffer += sizeof(prrtTimedelta_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
362

363 364 365
    prrtTimedelta_t *packet_timeout = (prrtTimedelta_t *) dstBuffer;
    data_payload->packetTimeout_us = ntohl(*packet_timeout);
    dstBuffer += sizeof(prrtTimedelta_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
366

Andreas Schmidt's avatar
Andreas Schmidt committed
367
    return dstBuffer;
368 369
}

370 371
int PrrtPacket_destroy(PrrtPacket *packet) {
    if (packet->payload != NULL) {
Andreas Schmidt's avatar
Andreas Schmidt committed
372
        free(packet->payload);
373
    }
Andreas Schmidt's avatar
Andreas Schmidt committed
374
    free(packet);
375 376 377
    return 0;
}

378
PrrtPacket *PrrtPacket_create_data_packet(uint8_t priority, const void *payloadPointer,
rna's avatar
rna committed
379
                                          prrtPacketLength_t dataLength, prrtSequenceNumber_t sequenceNumber,
380
                                          prrtTimedelta_t targetDelay) {
Andreas Schmidt's avatar
Andreas Schmidt committed
381
    PrrtPacket *packet = create_header(priority, sequenceNumber,
382 383
                                       (prrtPacketLength_t) (dataLength + PRRT_PACKET_DATA_HEADER_SIZE),
                                       PACKET_TYPE_DATA, 0);
384

385
    PrrtPacketDataPayload *dataPayload = calloc(1, packet->payloadLength);
Andreas Schmidt's avatar
Andreas Schmidt committed
386 387
    check_mem(dataPayload);
    packet->payload = dataPayload;
388

rna's avatar
rna committed
389
    dataPayload->dataLength = dataLength;
390
    dataPayload->timestamp = PrrtClock_get_current_time_us();
391
    dataPayload->packetTimeout_us = dataPayload->timestamp + targetDelay;
392
    dataPayload->groupRTprop_us = 0;
Andreas Schmidt's avatar
Andreas Schmidt committed
393
    PrrtPacket_copy_buffer_to_payload(packet, payloadPointer, PRRT_PACKET_DATA_HEADER_SIZE)
394

Andreas Schmidt's avatar
Andreas Schmidt committed
395
    return packet;
396

397
    error:
398
    PERROR("Could not create packet.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
399
    return NULL;
400 401
}

402 403
PrrtPacket *PrrtPacket_reconstruct_data_packet(PrrtPacketDataPayload *payload, prrtIndex_t index,
                                               prrtSequenceNumber_t sequenceNumber) {
rna's avatar
rna committed
404 405 406
    prrtPacketLength_t dataLength = payload->dataLength;

    PrrtPacket *packet = create_header(0, sequenceNumber,
407 408
                                       (prrtPacketLength_t) (dataLength + PRRT_PACKET_DATA_HEADER_SIZE),
                                       PACKET_TYPE_DATA, index);
rna's avatar
rna committed
409 410 411 412 413 414 415 416 417 418 419 420 421 422

    PrrtPacketDataPayload *dataPayload = calloc(1, packet->payloadLength);
    check_mem(dataPayload);
    packet->payload = dataPayload;

    PrrtPacket_copy_buffer_to_payload(packet, payload, 0)

    return packet;
    error:
    PERROR("Could not reconstruct packet.%s", "");
    return NULL;

}

423 424 425
PrrtPacket *PrrtPacket_create_redundancy_packet(uint8_t priority, void *payloadPointer,
                                                prrtPacketLength_t payloadLength,
                                                prrtSequenceNumber_t sequenceNumber, uint8_t index,
426 427
                                                prrtSequenceNumber_t baseSequenceNumber,
                                                PrrtCodingParams *codingParams) {
Andreas Schmidt's avatar
Andreas Schmidt committed
428
    PrrtPacket *packet = create_header(priority, sequenceNumber,
429
                                       (prrtPacketLength_t) (payloadLength + PRRT_PACKET_REDUNDANCY_HEADER_SIZE),
Andreas Schmidt's avatar
Andreas Schmidt committed
430
                                       PACKET_TYPE_REDUNDANCY, index);
431

432
    PrrtPacketRedundancyPayload *redundancyPayload = calloc(1, packet->payloadLength);
Andreas Schmidt's avatar
Andreas Schmidt committed
433 434
    check_mem(redundancyPayload);
    packet->payload = redundancyPayload;
435

436
    redundancyPayload->baseSequenceNumber = baseSequenceNumber;
437 438
    redundancyPayload->k = codingParams->k;
    redundancyPayload->n = codingParams->n;
Andreas Schmidt's avatar
Andreas Schmidt committed
439
    PrrtPacket_copy_buffer_to_payload(packet, payloadPointer, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
440

Andreas Schmidt's avatar
Andreas Schmidt committed
441
    return packet;
442 443

    error:
444
    PERROR("Out of memory%s.", "");
445
    return NULL;
446 447
}

448 449 450 451 452
PrrtPacket *PrrtPacket_create_feedback_packet(uint8_t priority, prrtSequenceNumber_t sequenceNumber, prrtTimedelta_t groupRTT,
                                              prrtSequenceNumber_t gapLength, prrtSequenceNumber_t gapCount,
                                              prrtSequenceNumber_t burstLength, prrtSequenceNumber_t burstCount,
                                              prrtTimestamp_t forwardTripTime, prrtSequenceNumber_t erasureCount,
                                              prrtSequenceNumber_t packetCount) {
Andreas Schmidt's avatar
Andreas Schmidt committed
453
    PrrtPacket *packet = create_header(priority, sequenceNumber, PRRT_PACKET_FEEDBACK_HEADER_SIZE, PACKET_TYPE_FEEDBACK,
454
                                       0);
Andreas Schmidt's avatar
Andreas Schmidt committed
455

456
    PrrtPacketFeedbackPayload *payload = calloc(1, packet->payloadLength);
457
    check_mem(payload);
Andreas Schmidt's avatar
Andreas Schmidt committed
458
    packet->payload = payload;
459

460 461
    payload->groupRTT_us = groupRTT;
    payload->forwardTripTimestamp_us = forwardTripTime;
Andreas Schmidt's avatar
Andreas Schmidt committed
462 463
    payload->erasureCount = erasureCount;
    payload->packetCount = packetCount;
464 465 466 467 468
    payload->gapLength = gapLength;
    payload->gapCount = gapCount;
    payload->burstLength = burstLength;
    payload->burstCount = burstCount;

469
    // TODO: Acknowledged packet.
470

Andreas Schmidt's avatar
Andreas Schmidt committed
471
    return packet;
472 473

    error:
474
    return NULL;
475
}