packet.c 20.9 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
57
58
        printf("| %61u |\n", payload->packetTimeout_us);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
        printf("| %61u |\n", payload->decodingTimeout_us);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
59
        printf("| %61u |\n", payload->feedbackTimer_us);
60
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
61
62
        printf("| %61s |\n", (char *) (packet_ptr->payload + PRRT_PACKET_DATA_HEADER_SIZE));
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
63
    } else if (type == PACKET_TYPE_REDUNDANCY) {
64
        PrrtPacketRedundancyPayload *payload = packet_ptr->payload;
65
        printf("| %29u | %13u | %13u |\n", payload->baseSequenceNumber, payload->n, payload->k);
66
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
67
    } else if (type == PACKET_TYPE_FEEDBACK) {
68
69
        prrtPacketLength_t i = 0;

70
        PrrtPacketFeedbackPayload *payload = packet_ptr->payload;
71
72

        struct sockaddr_in receiver;
73
74
        receiver.sin_addr.s_addr = payload->receiverAddress;
        char *address = inet_ntoa(receiver.sin_addr);
75
76
77

        printf("| %61s |\n", address);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
78
        printf("| %61u |\n", payload->groupRTT_us);
79
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
80
        printf("| %61u |\n", payload->forwardTripTimestamp_us);
81
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
82
        printf("| %29u | %29u |\n", payload->erasureCount, payload->packetCount);
83
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
84
        printf("| %29u | %29u |\n", payload->gapLength, payload->gapCount);
85
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
86
        printf("| %29u | %29u |\n", payload->burstLength, payload->burstCount);
87
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
88
        printf("| %61u |\n", payload->bandwidthEstimate);
89
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
90
91
92
93
94

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

95
        for (i = 0; i < blockCount; ++i) {
96
97
98
99
            PrrtIncompleteBlock block = payload->incompleteBlocks[i];
            printf("| %29u | %29u |\n", block.sequenceNumberBase, block.repairCycleIndex);
            printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
        }
100
    } else {
101
102
        printf("| Unhandeled Type                                               |\n");
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
103
104
105
106
107
    }

    return 0;
}

108
PrrtPacket *PrrtPacket_copy(PrrtPacket *original) {
109
110
    PrrtPacket *newPacket = calloc(1, sizeof(PrrtPacket));
    check_mem(newPacket);
111
    void *payload = calloc(1, original->payloadLength);
112
113
114
    check_mem(payload);

    newPacket->payload = payload;
115
116
    newPacket->payloadLength = original->payloadLength;
    memcpy(newPacket->payload, original->payload, original->payloadLength);
117
118

    newPacket->index = original->index;
119
    newPacket->sequenceNumber = original->sequenceNumber;
120
121
122
123
124
    newPacket->type_priority = original->type_priority;


    return newPacket;
    error:
125
    PERROR("Not enough memory for packet copies.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
126
    return NULL;
127
128
}

129
130
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
131
132
133
134
135
136
    PrrtPacket *packet = calloc(1, sizeof(PrrtPacket));
    check_mem(packet);

    packet->type_priority = type << 4;
    packet->type_priority |= priority & 0x0F;
    packet->index = index;
137
138
    packet->sequenceNumber = seqno;
    packet->payloadLength = size;
Andreas Schmidt's avatar
Andreas Schmidt committed
139
140
141
142
143

    return packet;

    error:
    PERROR("Could not create packet.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
144
    return NULL;
Andreas Schmidt's avatar
Andreas Schmidt committed
145
146
}

147
bool PrrtPacket_encode(void *buf_ptr, uint16_t buf_size, PrrtPacket *packet_ptr) {
148
    void *payload = packet_ptr->payload;
149

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

152
153
    buf_ptr = encode_general_header(buf_ptr, packet_ptr);

154
    prrtPacketType_t type = PrrtPacket_type(packet_ptr);
155
    if (type == PACKET_TYPE_DATA) {
156
        buf_ptr = encode_data_header(buf_ptr, payload);
157
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_DATA_HEADER_SIZE);
158
    } else if (type == PACKET_TYPE_REDUNDANCY) {
159
        buf_ptr = encode_redundancy_header(buf_ptr, payload);
160
        PrrtPacket_copy_payload_to_buffer(buf_ptr, packet_ptr, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
161
    } else if (type == PACKET_TYPE_FEEDBACK) {
162
        encode_feedback_header(buf_ptr, payload);
163
164
    } else {
        perror("NOT IMPLEMENTED");
165
        return false;
166
    }
167
    return true;
168
169

    error:
170
    return false;
171
172
}

173
void *encode_redundancy_header(void *buf_ptr, const void *payload) {
174
    const PrrtPacketRedundancyPayload *redundancyPayload = payload;
175

176
177
178
    prrtSequenceNumber_t *baseSeqNo = (prrtSequenceNumber_t *) buf_ptr;
    *baseSeqNo = htons(redundancyPayload->baseSequenceNumber);
    buf_ptr += sizeof(prrtSequenceNumber_t);
179
180
181

    uint8_t *n = (uint8_t *) buf_ptr;
    *n = redundancyPayload->n;
182
    buf_ptr += sizeof(uint8_t);
183
184
185

    uint8_t *k = (uint8_t *) buf_ptr;
    *k = redundancyPayload->k;
186
    buf_ptr += sizeof(uint8_t);
187
188
189
190

    return buf_ptr;
}

191
void *encode_feedback_header(void *buf_ptr, const void *payload) {
192
    const PrrtPacketFeedbackPayload *feedbackPayload = payload;
193

194
195
196
    uint32_t *receiverAddress = (uint32_t *) buf_ptr;
    *receiverAddress = feedbackPayload->receiverAddress;
    buf_ptr += sizeof(uint32_t);
197

198
199
200
    prrtTimedelta_t *groupRoundTripTime = (prrtTimedelta_t *) buf_ptr;
    *groupRoundTripTime = htonl(feedbackPayload->groupRTT_us);
    buf_ptr += sizeof(prrtTimedelta_t);
201

202
203
204
    prrtTimestamp_t *forwardTripTimestamp = (prrtTimestamp_t *) buf_ptr;
    *forwardTripTimestamp = htonl(feedbackPayload->forwardTripTimestamp_us);
    buf_ptr += sizeof(prrtTimestamp_t);
205

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

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

214
215
216
    prrtSequenceNumber_t *gap = (prrtSequenceNumber_t *) buf_ptr;
    *gap = htons(feedbackPayload->gapLength);
    buf_ptr += sizeof(prrtSequenceNumber_t);
217

218
219
220
    prrtSequenceNumber_t *ngap = (prrtSequenceNumber_t *) buf_ptr;
    *ngap = htons(feedbackPayload->gapCount);
    buf_ptr += sizeof(prrtSequenceNumber_t);
221

222
223
224
    prrtSequenceNumber_t *burstLength = (prrtSequenceNumber_t *) buf_ptr;
    *burstLength = htons(feedbackPayload->burstLength);
    buf_ptr += sizeof(prrtSequenceNumber_t);
225

226
227
228
    prrtSequenceNumber_t *burstCount = (prrtSequenceNumber_t *) buf_ptr;
    *burstCount = htons(feedbackPayload->burstCount);
    buf_ptr += sizeof(prrtSequenceNumber_t);
229

230
231
232
    uint32_t *bandwidth_estimate = (uint32_t *) buf_ptr;
    *bandwidth_estimate = htonl(feedbackPayload->bandwidthEstimate);
    buf_ptr += sizeof(uint32_t);
233

234
    // TODO: encode variable number of incomplete blocks
235
236
237
    return buf_ptr;
}

238
void *encode_data_header(void *buf_ptr, const void *payload) {
239
    const PrrtPacketDataPayload *data_payload = payload;
240

241
    prrtPacketLength_t *packetLength = (prrtPacketLength_t *) buf_ptr;
rna's avatar
rna committed
242
243
244
    *packetLength = htonl(data_payload->dataLength);
    buf_ptr += sizeof(prrtPacketLength_t);

245
    prrtTimestamp_t *timestamp = (prrtTimestamp_t *) buf_ptr;
246
    *timestamp = htonl(data_payload->timestamp);
247
    buf_ptr += sizeof(prrtTimestamp_t);
248

249
    prrtTimedelta_t *group_round_trip_time = (prrtTimedelta_t *) buf_ptr;
250
    *group_round_trip_time = htonl(data_payload->groupRTprop_us);
251
    buf_ptr += sizeof(prrtTimedelta_t);
252

253
254
255
    prrtTimedelta_t *packet_timeout = (prrtTimedelta_t *) buf_ptr;
    *packet_timeout = htonl(data_payload->packetTimeout_us);
    buf_ptr += sizeof(prrtTimedelta_t);
256

257
258
259
    prrtTimedelta_t *decoding_timeout = (prrtTimedelta_t *) buf_ptr;
    *decoding_timeout = htonl(data_payload->decodingTimeout_us);
    buf_ptr += sizeof(prrtTimedelta_t);
260

261
    prrtTimedelta_t *feedback_timeout = (prrtTimedelta_t *) buf_ptr;
262
    *feedback_timeout = htonl(data_payload->feedbackTimer_us);
263
    buf_ptr += sizeof(prrtTimedelta_t);
264
265
266
    return buf_ptr;
}

267
void *encode_general_header(void *buf_ptr, const PrrtPacket *packet) {
268
    uint8_t *type_priority = (uint8_t *) buf_ptr;
269
    *type_priority = packet->type_priority;
270
    buf_ptr += sizeof(uint8_t);
271

272
    uint8_t *index = (uint8_t *) buf_ptr;
273
    *index = packet->index;
274
    buf_ptr += sizeof(uint8_t);
275

276
277
278
    prrtSequenceNumber_t *seqno = (prrtSequenceNumber_t *) buf_ptr;
    *seqno = htons(packet->sequenceNumber);
    buf_ptr += sizeof(prrtSequenceNumber_t);
279

280
    return buf_ptr;
281
282
}

283
bool PrrtPacket_decode(void *srcBuffer, uint16_t srcBufferSize, PrrtPacket *targetPacket) {
284
    prrtPacketLength_t payload_len = (prrtPacketLength_t) (srcBufferSize - PRRT_PACKET_GENERAL_HEADER_SIZE);
Andreas Schmidt's avatar
Andreas Schmidt committed
285
286
287
288
289
    targetPacket->type_priority = *(uint8_t *) srcBuffer;
    srcBuffer += 1;
    uint8_t *index_ptr = (uint8_t *) srcBuffer;
    targetPacket->index = *index_ptr;
    srcBuffer += 1;
290
291
292
    prrtSequenceNumber_t *seqno_prt = (prrtSequenceNumber_t *) srcBuffer;
    targetPacket->sequenceNumber = ntohs(*seqno_prt);
    srcBuffer += sizeof(prrtSequenceNumber_t);
293

Andreas Schmidt's avatar
Andreas Schmidt committed
294
    void *payload_buffer = calloc(1, payload_len);
295
296
    check_mem(payload_buffer);

Andreas Schmidt's avatar
Andreas Schmidt committed
297
    targetPacket->payload = payload_buffer;
298
    targetPacket->payloadLength = payload_len;
Andreas Schmidt's avatar
Andreas Schmidt committed
299

300
    prrtPacketType_t packetType = PrrtPacket_type(targetPacket);
301
    if (packetType == PACKET_TYPE_DATA) {
Andreas Schmidt's avatar
Andreas Schmidt committed
302
303
        srcBuffer = decode_data_header(srcBuffer, payload_buffer);
        PrrtPacket_copy_buffer_to_payload(targetPacket, srcBuffer, PRRT_PACKET_DATA_HEADER_SIZE);
304
    } else if (packetType == PACKET_TYPE_REDUNDANCY) {
Andreas Schmidt's avatar
Andreas Schmidt committed
305
306
        srcBuffer = decode_redundancy_header(srcBuffer, payload_buffer);
        PrrtPacket_copy_buffer_to_payload(targetPacket, srcBuffer, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
307
    } else if (packetType == PACKET_TYPE_FEEDBACK) {
308
        decode_feedback_header(srcBuffer, payload_buffer);
Andreas Schmidt's avatar
Andreas Schmidt committed
309
    } else {
310
        printf("NOT IMPLEMENTED\n");
Andreas Schmidt's avatar
Andreas Schmidt committed
311
    }
312
    return true;
313
314

    error:
315
    return false;
Andreas Schmidt's avatar
Andreas Schmidt committed
316
}
317

318
void *decode_redundancy_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
319
    PrrtPacketRedundancyPayload *redundancyPayload = (PrrtPacketRedundancyPayload *) srcBuffer;
320

321
322
323
    prrtSequenceNumber_t *baseSeqNo = (prrtSequenceNumber_t *) dstBuffer;
    redundancyPayload->baseSequenceNumber = ntohs(*baseSeqNo);
    dstBuffer += sizeof(prrtSequenceNumber_t);
324

Andreas Schmidt's avatar
Andreas Schmidt committed
325
    uint8_t *n = (uint8_t *) dstBuffer;
326
    redundancyPayload->n = *n;
327
    dstBuffer += sizeof(uint8_t);
328

Andreas Schmidt's avatar
Andreas Schmidt committed
329
    uint8_t *k = (uint8_t *) dstBuffer;
330
    redundancyPayload->k = *k;
331
    dstBuffer += sizeof(uint8_t);
332

Andreas Schmidt's avatar
Andreas Schmidt committed
333
    return dstBuffer;
334
335
}

336
void *decode_feedback_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
337
    PrrtPacketFeedbackPayload *feedback_payload = (PrrtPacketFeedbackPayload *) srcBuffer;
338

Andreas Schmidt's avatar
Andreas Schmidt committed
339
    uint32_t *receiverAddr = (uint32_t *) dstBuffer;
340
341
    feedback_payload->receiverAddress = *receiverAddr;
    dstBuffer += sizeof(uint32_t);
342

343
344
345
    prrtTimedelta_t *groupRoundTripTime = (prrtTimedelta_t *) dstBuffer;
    feedback_payload->groupRTT_us = ntohl(*groupRoundTripTime);
    dstBuffer += sizeof(prrtTimedelta_t);
346

347
348
349
    prrtTimestamp_t *forwardTripTime = (prrtTimestamp_t *) dstBuffer;
    feedback_payload->forwardTripTimestamp_us = ntohl(*forwardTripTime);
    dstBuffer += sizeof(prrtTimestamp_t);
350

351
352
353
    prrtSequenceNumber_t *erasureCount = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->erasureCount = ntohs(*erasureCount);
    dstBuffer += sizeof(prrtSequenceNumber_t);
354

355
356
357
    prrtSequenceNumber_t *packetCount = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->packetCount = ntohs(*packetCount);
    dstBuffer += sizeof(prrtSequenceNumber_t);
358

359
360
361
    prrtSequenceNumber_t *gap = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->gapLength = ntohs(*gap);
    dstBuffer += sizeof(prrtSequenceNumber_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
362

363
364
365
    prrtSequenceNumber_t *ngap = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->gapCount = ntohs(*ngap);
    dstBuffer += sizeof(prrtSequenceNumber_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
366

367
368
369
    prrtSequenceNumber_t *burst = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->burstLength = ntohs(*burst);
    dstBuffer += sizeof(prrtSequenceNumber_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
370

371
372
373
    prrtSequenceNumber_t *nburst = (prrtSequenceNumber_t *) dstBuffer;
    feedback_payload->burstCount = ntohs(*nburst);
    dstBuffer += sizeof(prrtSequenceNumber_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
374

375
376
377
    uint32_t *bandwidthEstimate = (uint32_t *) dstBuffer;
    feedback_payload->bandwidthEstimate = ntohl(*bandwidthEstimate);
    dstBuffer += sizeof(uint32_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
378

379
    // TODO: decode variable number of incomplete blocks
Andreas Schmidt's avatar
Andreas Schmidt committed
380
    return dstBuffer;
Andreas Schmidt's avatar
Andreas Schmidt committed
381
382
}

383
void *decode_data_header(void *dstBuffer, const void *srcBuffer) {
Andreas Schmidt's avatar
Andreas Schmidt committed
384
    PrrtPacketDataPayload *data_payload = (PrrtPacketDataPayload *) srcBuffer;
Andreas Schmidt's avatar
Andreas Schmidt committed
385

rna's avatar
rna committed
386
387
388
389
    prrtPacketLength_t *dataLength = (prrtPacketLength_t *) dstBuffer;
    data_payload->dataLength = ntohl(*dataLength);
    dstBuffer += sizeof(prrtPacketLength_t);

390
    prrtTimestamp_t *timestamp = (prrtTimestamp_t *) dstBuffer;
Andreas Schmidt's avatar
Andreas Schmidt committed
391
    data_payload->timestamp = ntohl(*timestamp);
392
    dstBuffer += sizeof(prrtTimestamp_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
393

394
    prrtTimedelta_t *group_round_trip_time = (prrtTimedelta_t *) dstBuffer;
395
    data_payload->groupRTprop_us = ntohl(*group_round_trip_time);
396
    dstBuffer += sizeof(prrtTimedelta_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
397

398
399
400
    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
401

402
403
404
    prrtTimedelta_t *decoding_timeout = (prrtTimedelta_t *) dstBuffer;
    data_payload->decodingTimeout_us = ntohl(*decoding_timeout);
    dstBuffer += sizeof(prrtTimedelta_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
405

406
    prrtTimedelta_t *feedback_timeout = (prrtTimedelta_t *) dstBuffer;
407
    data_payload->feedbackTimer_us = ntohl(*feedback_timeout);
408
    dstBuffer += sizeof(prrtTimedelta_t);
Andreas Schmidt's avatar
Andreas Schmidt committed
409
    return dstBuffer;
410
411
}

412
413
int PrrtPacket_destroy(PrrtPacket *packet) {
    if (packet->payload != NULL) {
Andreas Schmidt's avatar
Andreas Schmidt committed
414
        free(packet->payload);
415
    }
Andreas Schmidt's avatar
Andreas Schmidt committed
416
    free(packet);
417
418
419
    return 0;
}

420
PrrtPacket *PrrtPacket_create_data_packet(uint8_t priority, const void *payloadPointer,
rna's avatar
rna committed
421
                                          prrtPacketLength_t dataLength, prrtSequenceNumber_t sequenceNumber,
422
                                          prrtTimedelta_t targetDelay) {
Andreas Schmidt's avatar
Andreas Schmidt committed
423
    PrrtPacket *packet = create_header(priority, sequenceNumber,
424
425
                                       (prrtPacketLength_t) (dataLength + PRRT_PACKET_DATA_HEADER_SIZE),
                                       PACKET_TYPE_DATA, 0);
426

427
    PrrtPacketDataPayload *dataPayload = calloc(1, packet->payloadLength);
Andreas Schmidt's avatar
Andreas Schmidt committed
428
429
    check_mem(dataPayload);
    packet->payload = dataPayload;
430

rna's avatar
rna committed
431
    dataPayload->dataLength = dataLength;
432
    dataPayload->timestamp = PrrtClock_get_current_time_us();
433
    dataPayload->packetTimeout_us = dataPayload->timestamp + targetDelay;
434
    dataPayload->groupRTprop_us = 0;
435
    dataPayload->decodingTimeout_us = 150; // TODO: payload->decodingTimeout_us
436
    dataPayload->feedbackTimer_us = 170; // TODO: payload->feedback_timer
Andreas Schmidt's avatar
Andreas Schmidt committed
437
    PrrtPacket_copy_buffer_to_payload(packet, payloadPointer, PRRT_PACKET_DATA_HEADER_SIZE)
438

Andreas Schmidt's avatar
Andreas Schmidt committed
439
    return packet;
440

441
    error:
442
    PERROR("Could not create packet.%s", "");
Andreas Schmidt's avatar
Andreas Schmidt committed
443
    return NULL;
444
445
}

446
447
PrrtPacket *PrrtPacket_reconstruct_data_packet(PrrtPacketDataPayload *payload, prrtIndex_t index,
                                               prrtSequenceNumber_t sequenceNumber) {
rna's avatar
rna committed
448
449
450
    prrtPacketLength_t dataLength = payload->dataLength;

    PrrtPacket *packet = create_header(0, sequenceNumber,
451
452
                                       (prrtPacketLength_t) (dataLength + PRRT_PACKET_DATA_HEADER_SIZE),
                                       PACKET_TYPE_DATA, index);
rna's avatar
rna committed
453
454
455
456
457
458
459
460
461
462
463
464
465
466

    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;

}

467
468
469
PrrtPacket *PrrtPacket_create_redundancy_packet(uint8_t priority, void *payloadPointer,
                                                prrtPacketLength_t payloadLength,
                                                prrtSequenceNumber_t sequenceNumber, uint8_t index,
470
471
                                                prrtSequenceNumber_t baseSequenceNumber,
                                                PrrtCodingParams *codingParams) {
Andreas Schmidt's avatar
Andreas Schmidt committed
472
    PrrtPacket *packet = create_header(priority, sequenceNumber,
473
                                       (prrtPacketLength_t) (payloadLength + PRRT_PACKET_REDUNDANCY_HEADER_SIZE),
Andreas Schmidt's avatar
Andreas Schmidt committed
474
                                       PACKET_TYPE_REDUNDANCY, index);
475

476
    PrrtPacketRedundancyPayload *redundancyPayload = calloc(1, packet->payloadLength);
Andreas Schmidt's avatar
Andreas Schmidt committed
477
478
    check_mem(redundancyPayload);
    packet->payload = redundancyPayload;
479

480
    redundancyPayload->baseSequenceNumber = baseSequenceNumber;
481
482
    redundancyPayload->k = codingParams->k;
    redundancyPayload->n = codingParams->n;
Andreas Schmidt's avatar
Andreas Schmidt committed
483
    PrrtPacket_copy_buffer_to_payload(packet, payloadPointer, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
484

Andreas Schmidt's avatar
Andreas Schmidt committed
485
    return packet;
486
487

    error:
488
    PERROR("Out of memory%s.", "");
489
    return NULL;
490
491
}

492
PrrtPacket *PrrtPacket_create_feedback_packet(uint8_t priority, uint8_t index, prrtSequenceNumber_t sequenceNumber,
493
                                              prrtTimedelta_t groupRTT, prrtSequenceNumber_t gapLength,
494
495
                                              prrtSequenceNumber_t gapCount, prrtSequenceNumber_t burstLength,
                                              prrtSequenceNumber_t burstCount, uint32_t bandwidth,
Andreas Schmidt's avatar
Andreas Schmidt committed
496
497
                                              uint32_t receiverAddr, prrtTimestamp_t forwardTripTime,
                                              prrtSequenceNumber_t erasureCount, prrtSequenceNumber_t packetCount) {
Andreas Schmidt's avatar
Andreas Schmidt committed
498
499
500
    PrrtPacket *packet = create_header(priority, sequenceNumber, PRRT_PACKET_FEEDBACK_HEADER_SIZE, PACKET_TYPE_FEEDBACK,
                                       index);

501
    PrrtPacketFeedbackPayload *payload = calloc(1, packet->payloadLength);
502
    check_mem(payload);
Andreas Schmidt's avatar
Andreas Schmidt committed
503
    packet->payload = payload;
504

505
    payload->receiverAddress = receiverAddr;
506
507
    payload->groupRTT_us = groupRTT;
    payload->forwardTripTimestamp_us = forwardTripTime;
Andreas Schmidt's avatar
Andreas Schmidt committed
508
509
    payload->erasureCount = erasureCount;
    payload->packetCount = packetCount;
510
511
512
513
514
515
516
    payload->gapLength = gapLength;
    payload->gapCount = gapCount;
    payload->burstLength = burstLength;
    payload->burstCount = burstCount;
    payload->bandwidthEstimate = bandwidth;

    // TODO: insert incomplete blocks
517

Andreas Schmidt's avatar
Andreas Schmidt committed
518
    return packet;
519
520

    error:
521
    return NULL;
522
}