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

11
static void *encode_general_header(void *buf_ptr, const PrrtPacket *packet);
12

13
static void *encode_data_header(void *buf_ptr, const void *payload);
14

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

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

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

21
static void *decode_redundancy_header(void *dstBuffer, const void *srcBuffer);
22

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

25
prrtPacketLength_t PrrtPacket_size(PrrtPacket *packet_ptr) {
26
    return (prrtPacketLength_t) (packet_ptr->payloadLength + PRRT_PACKET_ENCODED_GENERAL_HEADER_LENGTH);
27
28
}

29
int PrrtPacket_print(PrrtPacket *packet_ptr) {
30
31
    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"
32
                   "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
33
    prrtPacketType_t type = PrrtPacket_type(packet_ptr);
34

35
    printf("| %5u | %5u | %13u | %29u |\n", type, PrrtPacket_priority(packet_ptr), packet_ptr->index,
36
           packet_ptr->sequenceNumber);
37
    printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
38

39
    if (type == PACKET_TYPE_DATA) {
40
        PrrtPacketDataPayload *payload = packet_ptr->payload;
41
42
        printf("| %61u |\n", payload->timestamp);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
Andreas Schmidt's avatar
Andreas Schmidt committed
43
        printf("| %61u |\n", payload->RTprop_us);
44
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
45
46
        printf("| %61u |\n", payload->packetTimeout_us);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
47
48
        printf("| %61s |\n", (char *) (packet_ptr->payload + PRRT_PACKET_DATA_HEADER_SIZE));
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
49
    } else if (type == PACKET_TYPE_REDUNDANCY) {
50
        PrrtPacketRedundancyPayload *payload = packet_ptr->payload;
51
        printf("| %29u | %13u | %13u |\n", payload->baseSequenceNumber, payload->n, payload->k);
52
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
53
    } else if (type == PACKET_TYPE_FEEDBACK) {
54
55
        prrtPacketLength_t i = 0;

56
        PrrtPacketFeedbackPayload *payload = packet_ptr->payload;
57

58
        printf("| %61u |\n", payload->forwardTripTimestamp_us);
59
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
60
        printf("| %29u | %29u |\n", payload->erasureCount, payload->packetCount);
61
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
62
        printf("| %29u | %29u |\n", payload->gapLength, payload->gapCount);
63
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
64
        printf("| %29u | %29u |\n", payload->burstLength, payload->burstCount);
65
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
66
67
68
69
70

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

71
        for (i = 0; i < blockCount; ++i) {
72
73
74
75
            PrrtIncompleteBlock block = payload->incompleteBlocks[i];
            printf("| %29u | %29u |\n", block.sequenceNumberBase, block.repairCycleIndex);
            printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
        }
76
    } else {
77
78
        printf("| Unhandeled Type                                               |\n");
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
79
80
81
82
83
    }

    return 0;
}

84
PrrtPacket *PrrtPacket_copy(PrrtPacket *original) {
85
86
87
88
89
    __sync_fetch_and_add(&original->refcount, 1);
    return original;
}

PrrtPacket *PrrtPacket_deepcopy(PrrtPacket *original) {
90
91
    PrrtPacket *newPacket = calloc(1, sizeof(PrrtPacket));
    check_mem(newPacket);
92
    void *payload = calloc(1, original->payloadLength);
93
94
95
    check_mem(payload);

    newPacket->payload = payload;
96
97
    newPacket->payloadLength = original->payloadLength;
    memcpy(newPacket->payload, original->payload, original->payloadLength);
98
99

    newPacket->index = original->index;
100
    newPacket->sequenceNumber = original->sequenceNumber;
101
102
    newPacket->type_priority = original->type_priority;

103
104
    newPacket->refcount = 1;

105
106
107

    return newPacket;
    error:
108
    PERROR("Not enough memory for packet copies.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
109
    return NULL;
110
111
}

112
113
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
114
115
116
117
118
119
    PrrtPacket *packet = calloc(1, sizeof(PrrtPacket));
    check_mem(packet);

    packet->type_priority = type << 4;
    packet->type_priority |= priority & 0x0F;
    packet->index = index;
120
121
    packet->sequenceNumber = seqno;
    packet->payloadLength = size;
122
    packet->refcount = 1;
Andreas Schmidt's avatar
Andreas Schmidt committed
123
124
125
126
127

    return packet;

    error:
    PERROR("Could not create packet.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
128
    return NULL;
Andreas Schmidt's avatar
Andreas Schmidt committed
129
130
}

131
bool PrrtPacket_encode_payload(void *buf_ptr, PrrtPacket *packet_ptr) {
132
    prrtPacketType_t type = PrrtPacket_type(packet_ptr);
133
    if (type == PACKET_TYPE_DATA) {
134
        buf_ptr = encode_data_header(buf_ptr, packet_ptr->payload);
135
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_DATA_HEADER_SIZE);
136
    } else if (type == PACKET_TYPE_REDUNDANCY) {
137
        buf_ptr = encode_redundancy_header(buf_ptr, packet_ptr->payload);
138
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
139
    } else if (type == PACKET_TYPE_FEEDBACK) {
140
        encode_feedback_header(buf_ptr, packet_ptr->payload);
141
142
    } else {
        perror("NOT IMPLEMENTED");
143
        return false;
144
    }
145
    return true;
146
147
148
}

bool PrrtPacket_encode(void *buf_ptr, uint16_t buf_size, PrrtPacket *packet_ptr) {
149
    
150
151
152
153
154
    check(packet_ptr->payloadLength + PRRT_PACKET_ENCODED_GENERAL_HEADER_LENGTH <= buf_size, "Buffer too small.");

    buf_ptr = encode_general_header(buf_ptr, packet_ptr);

    return PrrtPacket_encode_payload(buf_ptr, packet_ptr);
155
156

    error:
157
    return false;
158
159
}

160
#define identity(x) (x)
161

162
163
#define PrrtPacketField_encode(payload, buf_ptr, field_t, field, conversion) \
    do { \
164
165
166
167
        field_t PrrtPacketField_encode_value = conversion((payload)->field); \
        /* memcpy to avoid misaligned access.
         * The compiler will optimize this into appropriate mov instructions */ \
        memcpy(buf_ptr, &PrrtPacketField_encode_value, sizeof(field_t)); \
168
169
        (buf_ptr) += sizeof(field_t); \
    } while (false)
170

171
172
void *encode_redundancy_header(void *buf_ptr, const void *payload) {
    const PrrtPacketRedundancyPayload *redundancyPayload = payload;
173

174
    PrrtPacketField_encode(redundancyPayload, buf_ptr, prrtTimestamp_t, timestamp, htonl);
Andreas Schmidt's avatar
Andreas Schmidt committed
175
    PrrtPacketField_encode(redundancyPayload, buf_ptr, prrtTimedelta_t , btl_pace, htonl);
Andreas Schmidt's avatar
Andreas Schmidt committed
176
    PrrtPacketField_encode(redundancyPayload, buf_ptr, prrtSequenceNumber_t, baseSequenceNumber, htons);
177
178
    PrrtPacketField_encode(redundancyPayload, buf_ptr, uint8_t, n, identity);
    PrrtPacketField_encode(redundancyPayload, buf_ptr, uint8_t, k, identity);
179
180
181
182

    return buf_ptr;
}

183
void *encode_feedback_header(void *buf_ptr, const void *payload) {
184
    const PrrtPacketFeedbackPayload *feedbackPayload = payload;
185

186
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtTimestamp_t, forwardTripTimestamp_us, htonl);
Andreas Schmidt's avatar
Andreas Schmidt committed
187
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtTimedelta_t, btl_pace, htonl);
188
189
190
191
192
193
194
195
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtSequenceNumber_t, erasureCount, htons);
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtSequenceNumber_t, packetCount, htons);
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtSequenceNumber_t, gapLength, htons);
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtSequenceNumber_t, gapCount, htons);
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtSequenceNumber_t, burstLength, htons);
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtSequenceNumber_t, burstCount, htons);
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtPacketType_t, ackPacketType, identity);
    PrrtPacketField_encode(feedbackPayload, buf_ptr, prrtSequenceNumber_t, ackSequenceNumber, htons);
196

197
198
199
    return buf_ptr;
}

200
void *encode_data_header(void *buf_ptr, const void *payload) {
201
    const PrrtPacketDataPayload *data_payload = payload;
202

Andreas Schmidt's avatar
Andreas Schmidt committed
203
    PrrtPacketField_encode(data_payload, buf_ptr, prrtTimestamp_t, timestamp, htonl);
Andreas Schmidt's avatar
Andreas Schmidt committed
204
    PrrtPacketField_encode(data_payload, buf_ptr, prrtTimedelta_t, btl_pace, htonl);
205
    PrrtPacketField_encode(data_payload, buf_ptr, prrtPacketLength_t, dataLength, htonl);
Andreas Schmidt's avatar
Andreas Schmidt committed
206
    PrrtPacketField_encode(data_payload, buf_ptr, prrtTimedelta_t, RTprop_us, htonl);
rna's avatar
rna committed
207
    PrrtPacketField_encode(data_payload, buf_ptr, prrtTimestamp_t, packetTimeout_us, htonl);
Andreas Schmidt's avatar
Andreas Schmidt committed
208
    PrrtPacketField_encode(data_payload, buf_ptr, prrtDeliveryRate_t, btl_datarate, htonl);
209
210
211
212

    return buf_ptr;
}

213
void *encode_general_header(void *buf_ptr, const PrrtPacket *packet) {
214

215
216
217
    PrrtPacketField_encode(packet, buf_ptr, uint8_t, type_priority, identity);
    PrrtPacketField_encode(packet, buf_ptr, uint8_t, index, identity);
    PrrtPacketField_encode(packet, buf_ptr, prrtSequenceNumber_t, sequenceNumber, htons);
218

219
    return buf_ptr;
220
221
}

222
223
224
225
226
bool PrrtPacket_decode_payload(void *srcBuffer, prrtPacketType_t packetType, void *payload, uint32_t payload_len) {
    if (packetType == PACKET_TYPE_DATA) {
        srcBuffer = decode_data_header(srcBuffer, payload);
        memcpy(payload + PRRT_PACKET_DATA_HEADER_SIZE, srcBuffer, payload_len - PRRT_PACKET_DATA_HEADER_SIZE);
    } else if (packetType == PACKET_TYPE_REDUNDANCY) {
227
        srcBuffer = decode_redundancy_header(srcBuffer, payload);
228
229
230
231
232
233
234
235
236
237
        memcpy(payload + PRRT_PACKET_REDUNDANCY_HEADER_SIZE, srcBuffer, payload_len - PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
    } else if (packetType == PACKET_TYPE_FEEDBACK) {
        decode_feedback_header(srcBuffer, payload);
    } else {
        perror("NOT IMPLEMENTED\n");
        return false;
    }
    return true;
}

238
bool PrrtPacket_decode(void *srcBuffer, uint16_t srcBufferSize, PrrtPacket *targetPacket) {
239
240
241
242

    // targetPacket is uninitialized, so we need to set the reference count
    targetPacket->refcount = 1;

243
    prrtPacketLength_t payload_len = (prrtPacketLength_t) (srcBufferSize - PRRT_PACKET_ENCODED_GENERAL_HEADER_LENGTH);
Andreas Schmidt's avatar
Andreas Schmidt committed
244
245
246
247
248
    targetPacket->type_priority = *(uint8_t *) srcBuffer;
    srcBuffer += 1;
    uint8_t *index_ptr = (uint8_t *) srcBuffer;
    targetPacket->index = *index_ptr;
    srcBuffer += 1;
249
250
251
    prrtSequenceNumber_t *seqno_prt = (prrtSequenceNumber_t *) srcBuffer;
    targetPacket->sequenceNumber = ntohs(*seqno_prt);
    srcBuffer += sizeof(prrtSequenceNumber_t);
252

Andreas Schmidt's avatar
Andreas Schmidt committed
253
    void *payload_buffer = calloc(1, payload_len);
254
255
    check_mem(payload_buffer);

Andreas Schmidt's avatar
Andreas Schmidt committed
256
    targetPacket->payload = payload_buffer;
257
    targetPacket->payloadLength = payload_len;
Andreas Schmidt's avatar
Andreas Schmidt committed
258

259
    prrtPacketType_t packetType = PrrtPacket_type(targetPacket);
260
    return PrrtPacket_decode_payload(srcBuffer, packetType, payload_buffer, payload_len);
261
262

    error:
263
    return false;
Andreas Schmidt's avatar
Andreas Schmidt committed
264
}
265

266
267
#define PrrtPacketField_decode(payload, buf_ptr, field_t, field, conversion) \
    do { \
268
269
270
271
272
        field_t PrrtPacketField_decode_value; \
        /* memcpy to avoid misaligned access.
         * The compiler will optimize this into appropriate mov instructions */ \
        memcpy(&PrrtPacketField_decode_value, buf_ptr, sizeof(field_t)); \
        (payload)->field = conversion(PrrtPacketField_decode_value); \
273
274
275
        (buf_ptr) += sizeof(field_t); \
    } while (false)

276
void *decode_redundancy_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
277
    PrrtPacketRedundancyPayload *redundancyPayload = (PrrtPacketRedundancyPayload *) srcBuffer;
278

279
    PrrtPacketField_decode(redundancyPayload, dstBuffer, prrtTimestamp_t, timestamp, ntohl);
Andreas Schmidt's avatar
Andreas Schmidt committed
280
    PrrtPacketField_decode(redundancyPayload, dstBuffer, prrtTimedelta_t , btl_pace, ntohl);
Andreas Schmidt's avatar
Andreas Schmidt committed
281
    PrrtPacketField_decode(redundancyPayload, dstBuffer, prrtSequenceNumber_t, baseSequenceNumber, ntohs);
282
283
    PrrtPacketField_decode(redundancyPayload, dstBuffer, uint8_t, n, identity);
    PrrtPacketField_decode(redundancyPayload, dstBuffer, uint8_t, k, identity);
284

Andreas Schmidt's avatar
Andreas Schmidt committed
285
    return dstBuffer;
286
287
}

288
void *decode_feedback_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
289
    PrrtPacketFeedbackPayload *feedback_payload = (PrrtPacketFeedbackPayload *) srcBuffer;
290

291
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtTimestamp_t, forwardTripTimestamp_us, ntohl);
Andreas Schmidt's avatar
Andreas Schmidt committed
292
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtTimedelta_t, btl_pace, ntohl);
293
294
295
296
297
298
299
300
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtSequenceNumber_t, erasureCount, ntohs);
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtSequenceNumber_t, packetCount, ntohs);
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtSequenceNumber_t, gapLength, ntohs);
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtSequenceNumber_t, gapCount, ntohs);
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtSequenceNumber_t, burstLength, ntohs);
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtSequenceNumber_t, burstCount, ntohs);
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtPacketType_t, ackPacketType, identity);
    PrrtPacketField_decode(feedback_payload, dstBuffer, prrtSequenceNumber_t, ackSequenceNumber, ntohs);
301

Andreas Schmidt's avatar
Andreas Schmidt committed
302
    return dstBuffer;
Andreas Schmidt's avatar
Andreas Schmidt committed
303
304
}

305
void *decode_data_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
306
    PrrtPacketDataPayload *data_payload = (PrrtPacketDataPayload *) srcBuffer;
Andreas Schmidt's avatar
Andreas Schmidt committed
307

Andreas Schmidt's avatar
Andreas Schmidt committed
308
    PrrtPacketField_decode(data_payload, dstBuffer, prrtTimestamp_t, timestamp, ntohl);
Andreas Schmidt's avatar
Andreas Schmidt committed
309
    PrrtPacketField_decode(data_payload, dstBuffer, prrtTimedelta_t, btl_pace, ntohl);
310
    PrrtPacketField_decode(data_payload, dstBuffer, prrtPacketLength_t, dataLength, ntohl);
Andreas Schmidt's avatar
Andreas Schmidt committed
311
    PrrtPacketField_decode(data_payload, dstBuffer, prrtTimedelta_t, RTprop_us, ntohl);
312
    PrrtPacketField_decode(data_payload, dstBuffer, prrtTimedelta_t, packetTimeout_us, ntohl);
Andreas Schmidt's avatar
Andreas Schmidt committed
313
    PrrtPacketField_decode(data_payload, dstBuffer, prrtDeliveryRate_t, btl_datarate, ntohl);
Andreas Schmidt's avatar
Andreas Schmidt committed
314

Andreas Schmidt's avatar
Andreas Schmidt committed
315
    return dstBuffer;
316
317
}

318
int PrrtPacket_destroy(PrrtPacket *packet) {
319
320
321
322
323
324
325
326
327
328

    prrtRefcount_t refcount = __sync_fetch_and_sub(&packet->refcount, 1);
    if (refcount > 1) {
        return 0;
    } else {
        if (packet->payload != NULL) {
            free(packet->payload);
        }
        free(packet);
        return 0;
329
    }
330
331
}

332
PrrtPacket *PrrtPacket_create_data_packet(uint8_t priority, const void *payloadPointer,
rna's avatar
rna committed
333
                                          prrtPacketLength_t dataLength, prrtSequenceNumber_t sequenceNumber,
334
                                          prrtTimedelta_t targetDelay) {
Andreas Schmidt's avatar
Andreas Schmidt committed
335
    PrrtPacket *packet = create_header(priority, sequenceNumber,
336
337
                                       (prrtPacketLength_t) (dataLength + PRRT_PACKET_DATA_HEADER_SIZE),
                                       PACKET_TYPE_DATA, 0);
338

339
    PrrtPacketDataPayload *dataPayload = calloc(1, packet->payloadLength);
Andreas Schmidt's avatar
Andreas Schmidt committed
340
341
    check_mem(dataPayload);
    packet->payload = dataPayload;
342

rna's avatar
rna committed
343
    dataPayload->dataLength = dataLength;
344
    dataPayload->timestamp = PrrtClock_get_current_time_us();
345
    dataPayload->packetTimeout_us = dataPayload->timestamp + targetDelay;
Andreas Schmidt's avatar
Andreas Schmidt committed
346
    PrrtPacket_copy_buffer_to_payload(packet, payloadPointer, PRRT_PACKET_DATA_HEADER_SIZE)
347

Andreas Schmidt's avatar
Andreas Schmidt committed
348
    return packet;
349

350
    error:
351
    PERROR("Could not create packet.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
352
    return NULL;
353
354
}

355
356
PrrtPacket *PrrtPacket_reconstruct_data_packet(PrrtPacketDataPayload *payload, prrtIndex_t index,
                                               prrtSequenceNumber_t sequenceNumber) {
rna's avatar
rna committed
357
358
359
    prrtPacketLength_t dataLength = payload->dataLength;

    PrrtPacket *packet = create_header(0, sequenceNumber,
360
361
                                       (prrtPacketLength_t) (dataLength + PRRT_PACKET_DATA_HEADER_SIZE),
                                       PACKET_TYPE_DATA, index);
rna's avatar
rna committed
362
363
364
365
366
367
368
369
370
371
372
373
374
375

    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;

}

376
377
378
PrrtPacket *PrrtPacket_create_redundancy_packet(uint8_t priority, void *payloadPointer,
                                                prrtPacketLength_t payloadLength,
                                                prrtSequenceNumber_t sequenceNumber, uint8_t index,
379
                                                prrtSequenceNumber_t baseSequenceNumber,
380
                                                PrrtCodingConfiguration *codingParams) {
Andreas Schmidt's avatar
Andreas Schmidt committed
381
    PrrtPacket *packet = create_header(priority, sequenceNumber,
382
                                       (prrtPacketLength_t) (payloadLength + PRRT_PACKET_REDUNDANCY_HEADER_SIZE),
Andreas Schmidt's avatar
Andreas Schmidt committed
383
                                       PACKET_TYPE_REDUNDANCY, index);
384

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

389
    redundancyPayload->baseSequenceNumber = baseSequenceNumber;
390
    redundancyPayload->timestamp = PrrtClock_get_current_time_us();
391
392
    redundancyPayload->k = codingParams->k;
    redundancyPayload->n = codingParams->n;
Andreas Schmidt's avatar
Andreas Schmidt committed
393
    PrrtPacket_copy_buffer_to_payload(packet, payloadPointer, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
394

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

    error:
398
    PERROR("Out of memory%s.", "");
399
    return NULL;
400
401
}

402
PrrtPacket *
Andreas Schmidt's avatar
Andreas Schmidt committed
403
PrrtPacket_create_feedback_packet(uint8_t priority, prrtSequenceNumber_t sequenceNumber,
404
405
406
407
                                  prrtSequenceNumber_t gapLength, prrtSequenceNumber_t gapCount,
                                  prrtSequenceNumber_t burstLength, prrtSequenceNumber_t burstCount,
                                  prrtTimestamp_t forwardTripTime, prrtSequenceNumber_t erasureCount,
                                  prrtSequenceNumber_t packetCount, prrtSequenceNumber_t ackSequenceNumber,
Andreas Schmidt's avatar
Andreas Schmidt committed
408
                                  prrtPacketType_t ackPacketType, prrtTimedelta_t btl_pace) {
Andreas Schmidt's avatar
Andreas Schmidt committed
409
    PrrtPacket *packet = create_header(priority, sequenceNumber, PRRT_PACKET_FEEDBACK_HEADER_SIZE, PACKET_TYPE_FEEDBACK,
410
                                       0);
Andreas Schmidt's avatar
Andreas Schmidt committed
411

412
    PrrtPacketFeedbackPayload *payload = calloc(1, packet->payloadLength);
413
    check_mem(payload);
Andreas Schmidt's avatar
Andreas Schmidt committed
414
    packet->payload = payload;
Andreas Schmidt's avatar
Andreas Schmidt committed
415
    payload->btl_pace = btl_pace;
416
    payload->forwardTripTimestamp_us = forwardTripTime;
Andreas Schmidt's avatar
Andreas Schmidt committed
417
418
    payload->erasureCount = erasureCount;
    payload->packetCount = packetCount;
419
420
421
422
    payload->gapLength = gapLength;
    payload->gapCount = gapCount;
    payload->burstLength = burstLength;
    payload->burstCount = burstCount;
423
424
    payload->ackSequenceNumber = ackSequenceNumber;
    payload->ackPacketType = ackPacketType;
425

Andreas Schmidt's avatar
Andreas Schmidt committed
426
    return packet;
427
428

    error:
429
    return NULL;
430
}