packet.c 16.1 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>
Andreas Schmidt's avatar
Andreas Schmidt committed
6
7
#include <src/util/dbg.h>
#include "packet.h"
8

9
void *encode_general_header(void *buf_ptr, const PrrtPacket *packet);
10

11
void *encode_data_header(void *buf_ptr, const void *payload);
12

13
void *encode_redundancy_header(void *buf_ptr, const void *payload);
14

15
void *encode_feedback_header(void *buf_ptr, const void *payload);
16

Andreas Schmidt's avatar
Andreas Schmidt committed
17
18
void *decode_data_header(void *buf_ptr, const void *payload_ptr);

19
20
void *decode_redundancy_header(void *buf_ptr, const void *payload_ptr);

21
void *decode_feedback_header(void *buf_ptr, const void *payload_ptr);
Andreas Schmidt's avatar
Andreas Schmidt committed
22

23
uint8_t PrrtPacket_type(PrrtPacket *packet_ptr) {
24
25
26
    return (uint8_t) ((packet_ptr->type_priority >> 4) & 0x0F);
}

27
uint8_t PrrtPacket_priority(PrrtPacket *packet_ptr) {
28
29
30
    return (uint8_t) (packet_ptr->type_priority & 0x0F);
}

31
uint16_t PrrtPacket_size(PrrtPacket *packet_ptr) {
Andreas Schmidt's avatar
Andreas Schmidt committed
32
    return (uint16_t) (packet_ptr->payload_len + PRRT_PACKET_GENERAL_HEADER_SIZE);
33
34
}

35
int PrrtPacket_print(PrrtPacket *packet_ptr) {
36
37
    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"
38
                   "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
39
    uint8_t type = PrrtPacket_type(packet_ptr);
40

41
42
    printf("| %5u | %5u | %13u | %29u |\n", type, PrrtPacket_priority(packet_ptr), packet_ptr->index,
           packet_ptr->seqno);
43
    printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
44

45
46
    if (type == PACKET_TYPE_DATA) {
        PrrtPacketDataPayload *payload = packet_ptr->payload;
47
48
49
50
        printf("| %61u |\n", payload->timestamp);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
        printf("| %29u | %29u |\n", payload->group_round_trip_time, payload->packet_timeout);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
51
52
        printf("| %29u | %29u |\n", payload->decoding_timeout, payload->feedback_timeout);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
53
54
55
56
57
58
    } else if (type == PACKET_TYPE_REDUNDANCY) {
        PrrtPacketRedundancyPayload *payload = packet_ptr->payload;
        printf("| %29u | %13u | %13u |\n", payload->base_seqno, payload->n, payload->k);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
    } else if (type == PACKET_TYPE_FEEDBACK) {
        PrrtPacketFeedbackPayload *payload = packet_ptr->payload;
59
        printf("| %61u |\n", payload->group_round_trip_time);
60
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
61
        printf("| %61u |\n", payload->forward_trip_time);
62
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
63
        printf("| %61u |\n", payload->packet_loss_rate);
64
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
65
        printf("| %29u | %29u |\n", payload->gap, payload->ngap);
66
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
67
        printf("| %29u | %29u |\n", payload->burst, payload->nburst);
68
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
69
        printf("| %61u |\n", payload->bandwidth_estimate);
70
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
71
72
        printf("| %61u |\n", payload->buffer_feedback);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
73
    } else {
74
75
        printf("| Unhandeled Type                                               |\n");
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
76
77
78
79
80
    }

    return 0;
}

81
int PrrtPacket_encode(void *buf_ptr, uint16_t buf_size, PrrtPacket *packet_ptr) {
82
    void *payload = packet_ptr->payload;
83

84
    check(packet_ptr->payload_len + PRRT_PACKET_GENERAL_HEADER_SIZE <= buf_size, "Buffer too small.");
85

86
87
    buf_ptr = encode_general_header(buf_ptr, packet_ptr);

88
    uint8_t type = PrrtPacket_type(packet_ptr);
89
    if (type == PACKET_TYPE_DATA) {
90
91
        buf_ptr = encode_data_header(buf_ptr, payload);
        memcpy(buf_ptr, payload + PRRT_PACKET_DATA_HEADER_SIZE, packet_ptr->payload_len - PRRT_PACKET_DATA_HEADER_SIZE);
92
93
94
95
    } else if (type == PACKET_TYPE_REDUNDANCY) {
        buf_ptr = encode_redundancy_header(buf_ptr, payload);
        memcpy(buf_ptr, payload + PRRT_PACKET_REDUNDANCY_HEADER_SIZE,
               packet_ptr->payload_len - PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
96
97
    } else if (type == PACKET_TYPE_FEEDBACK) {
        buf_ptr = encode_feedback_header(buf_ptr, payload);
98
99
        memcpy(buf_ptr, payload + PRRT_PACKET_FEEDBACK_HEADER_SIZE,
               packet_ptr->payload_len - PRRT_PACKET_FEEDBACK_HEADER_SIZE);
100
101
102
103
104
    } else {
        perror("NOT IMPLEMENTED");
        return -1;
    }
    return 0;
105
106
107

    error:
        return -1;
108
109
}

110
void *encode_redundancy_header(void *buf_ptr, const void *payload) {
111
    const PrrtPacketRedundancyPayload *redundancyPayload = payload;
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

    uint16_t *baseSeqNo = (uint16_t *) buf_ptr;
    *baseSeqNo = htons(redundancyPayload->base_seqno);
    buf_ptr += 2;

    uint8_t *n = (uint8_t *) buf_ptr;
    *n = redundancyPayload->n;
    buf_ptr += 1;

    uint8_t *k = (uint8_t *) buf_ptr;
    *k = redundancyPayload->k;
    buf_ptr += 1;

    return buf_ptr;
}

128
void *encode_feedback_header(void *buf_ptr, const void *payload) {
129
    const PrrtPacketFeedbackPayload *feedbackPayload = payload;
130
131

    uint32_t *receiver_ip = (uint32_t *) buf_ptr;
132
    *receiver_ip = htonl(feedbackPayload->receiver_addr);
133
134
135
    buf_ptr += 4;

    uint32_t *group_round_trip_time = (uint32_t *) buf_ptr;
136
137
    *group_round_trip_time = htonl(feedbackPayload->group_round_trip_time);
    buf_ptr += 4;
138
139

    uint32_t *forward_trip_time = (uint32_t *) buf_ptr;
140
141
    *forward_trip_time = htonl(feedbackPayload->forward_trip_time);
    buf_ptr += 4;
142
143

    uint32_t *packet_loss_rate = (uint32_t *) buf_ptr;
144
145
    *packet_loss_rate = htonl(feedbackPayload->packet_loss_rate);
    buf_ptr += 4;
146
147

    uint16_t *gap = (uint16_t *) buf_ptr;
148
149
    *gap = htons(feedbackPayload->gap);
    buf_ptr += 2;
150
151

    uint16_t *ngap = (uint16_t *) buf_ptr;
152
153
    *ngap = htons(feedbackPayload->ngap);
    buf_ptr += 2;
154
155

    uint16_t *burst = (uint16_t *) buf_ptr;
156
157
    *burst = htons(feedbackPayload->burst);
    buf_ptr += 2;
158
159

    uint16_t *nburst = (uint16_t *) buf_ptr;
160
161
    *nburst = htons(feedbackPayload->nburst);
    buf_ptr += 2;
162
163

    uint32_t *bandwidth_estimate = (uint32_t *) buf_ptr;
164
165
    *bandwidth_estimate = htonl(feedbackPayload->bandwidth_estimate);
    buf_ptr += 4;
166
167

    uint32_t *buffer_feedback = (uint32_t *) buf_ptr;
168
169
    *buffer_feedback = htonl(feedbackPayload->buffer_feedback);
    buf_ptr += 4;
170
171
172
173

    return buf_ptr;
}

174
void *encode_data_header(void *buf_ptr, const void *payload) {
175
    const PrrtPacketDataPayload *data_payload = payload;
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

    uint32_t *timestamp = (uint32_t *) buf_ptr;
    *timestamp = htonl(data_payload->timestamp);
    buf_ptr += 4;

    uint16_t *group_round_trip_time = (uint16_t *) buf_ptr;
    *group_round_trip_time = htons(data_payload->group_round_trip_time);
    buf_ptr += 2;

    uint16_t *packet_timeout = (uint16_t *) buf_ptr;
    *packet_timeout = htons(data_payload->packet_timeout);
    buf_ptr += 2;

    uint16_t *decoding_timeout = (uint16_t *) buf_ptr;
    *decoding_timeout = htons(data_payload->decoding_timeout);
    buf_ptr += 2;

    uint16_t *feedback_timeout = (uint16_t *) buf_ptr;
    *feedback_timeout = htons(data_payload->feedback_timeout);
    buf_ptr += 2;
    return buf_ptr;
}

199
void *encode_general_header(void *buf_ptr, const PrrtPacket *packet) {
200
    uint8_t *type_priority = (uint8_t *) buf_ptr;
201
202
    *type_priority = packet->type_priority;
    buf_ptr += 1;
203

204
    uint8_t *index = (uint8_t *) buf_ptr;
205
206
    *index = packet->index;
    buf_ptr += 1;
207

208
    uint16_t *seqno = (uint16_t *) buf_ptr;
209
210
    *seqno = htons(packet->seqno);
    buf_ptr += 2;
211

212
    return buf_ptr;
213
214
}

215
int PrrtPacket_decode(void *buf_ptr, uint16_t buf_size, PrrtPacket *packet_ptr) {
216
    uint32_t payload_len = (uint32_t) (buf_size - PRRT_PACKET_GENERAL_HEADER_SIZE);
217
    packet_ptr->type_priority = *(uint8_t *) buf_ptr;
Andreas Schmidt's avatar
Andreas Schmidt committed
218
    buf_ptr += 1;
219
    uint8_t *index_ptr = (uint8_t *) buf_ptr;
220
    packet_ptr->index = *index_ptr;
Andreas Schmidt's avatar
Andreas Schmidt committed
221
    buf_ptr += 1;
222
    uint16_t *seqno_prt = (uint16_t *) buf_ptr;
223
    packet_ptr->seqno = ntohs(*seqno_prt);
Andreas Schmidt's avatar
Andreas Schmidt committed
224
    buf_ptr += 2;
225

226
    void *payload_buffer = malloc(payload_len);
227
228
    check_mem(payload_buffer);

Andreas Schmidt's avatar
Andreas Schmidt committed
229
230
    packet_ptr->payload = payload_buffer;
    packet_ptr->payload_len = payload_len;
231

232
    if (PrrtPacket_type(packet_ptr) == PACKET_TYPE_DATA) {
Andreas Schmidt's avatar
Andreas Schmidt committed
233
234
        buf_ptr = decode_data_header(buf_ptr, payload_buffer);
        memcpy(payload_buffer + PRRT_PACKET_DATA_HEADER_SIZE, buf_ptr, payload_len - PRRT_PACKET_DATA_HEADER_SIZE);
235
236
237
238
    } else if(PrrtPacket_type(packet_ptr)) {
        buf_ptr = decode_redundancy_header(buf_ptr, payload_buffer);
        memcpy(payload_buffer + PRRT_PACKET_REDUNDANCY_HEADER_SIZE, buf_ptr, payload_len - PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
    } else if (PrrtPacket_type(packet_ptr) == PACKET_TYPE_FEEDBACK) {
Andreas Schmidt's avatar
Andreas Schmidt committed
239
        buf_ptr = decode_feedback_header(buf_ptr, payload_buffer);
240
241
        memcpy(payload_buffer + PRRT_PACKET_FEEDBACK_HEADER_SIZE, buf_ptr,
               payload_len - PRRT_PACKET_FEEDBACK_HEADER_SIZE);
Andreas Schmidt's avatar
Andreas Schmidt committed
242
    } else {
243
        printf("NOT IMPLEMENTED\n");
Andreas Schmidt's avatar
Andreas Schmidt committed
244
245
    }
    return 0;
246
247
248

    error:
        return EXIT_FAILURE;
Andreas Schmidt's avatar
Andreas Schmidt committed
249
}
250

251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
void *decode_redundancy_header(void *buf_ptr, const void *payload_ptr) {
    PrrtPacketRedundancyPayload* redundancyPayload = (PrrtPacketRedundancyPayload *) payload_ptr;

    uint16_t *baseSeqNo = (uint16_t *) buf_ptr;
    redundancyPayload->base_seqno = ntohs(*baseSeqNo);
    buf_ptr += 2;

    uint8_t *n = (uint8_t *) buf_ptr;
    redundancyPayload->n = *n;
    buf_ptr += 1;

    uint8_t *k = (uint8_t *) buf_ptr;
    redundancyPayload->k = *k;
    buf_ptr += 1;

    return buf_ptr;
}

269
void *decode_feedback_header(void *buf_ptr, const void *payload_ptr) {
270
    PrrtPacketFeedbackPayload *feedback_payload = (PrrtPacketFeedbackPayload *) payload_ptr;
271

Andreas Schmidt's avatar
Andreas Schmidt committed
272
273
274
    uint32_t *receiver_addr = (uint32_t *) buf_ptr;
    feedback_payload->receiver_addr = ntohl(*receiver_addr);
    buf_ptr += 4;
275

Andreas Schmidt's avatar
Andreas Schmidt committed
276
277
278
    uint32_t *group_round_trip_time = (uint32_t *) buf_ptr;
    feedback_payload->group_round_trip_time = ntohl(*group_round_trip_time);
    buf_ptr += 4;
279

Andreas Schmidt's avatar
Andreas Schmidt committed
280
281
282
    uint32_t *forward_trip_time = (uint32_t *) buf_ptr;
    feedback_payload->forward_trip_time = ntohl(*forward_trip_time);
    buf_ptr += 4;
283

Andreas Schmidt's avatar
Andreas Schmidt committed
284
285
286
    uint32_t *packet_loss_rate = (uint32_t *) buf_ptr;
    feedback_payload->packet_loss_rate = ntohl(*packet_loss_rate);
    buf_ptr += 4;
287

Andreas Schmidt's avatar
Andreas Schmidt committed
288
289
290
    uint16_t *gap = (uint16_t *) buf_ptr;
    feedback_payload->gap = ntohs(*gap);
    buf_ptr += 2;
291

Andreas Schmidt's avatar
Andreas Schmidt committed
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
    uint16_t *ngap = (uint16_t *) buf_ptr;
    feedback_payload->ngap = ntohs(*ngap);
    buf_ptr += 2;

    uint16_t *burst = (uint16_t *) buf_ptr;
    feedback_payload->burst = ntohs(*burst);
    buf_ptr += 2;

    uint16_t *nburst = (uint16_t *) buf_ptr;
    feedback_payload->nburst = ntohs(*nburst);
    buf_ptr += 2;

    uint32_t *bandwidth_estimate = (uint32_t *) buf_ptr;
    feedback_payload->bandwidth_estimate = ntohl(*bandwidth_estimate);
    buf_ptr += 4;

    uint32_t *buffer_feedback = (uint32_t *) buf_ptr;
    feedback_payload->buffer_feedback = ntohl(*buffer_feedback);
    buf_ptr += 4;

    return buf_ptr;
}

void *decode_data_header(void *buf_ptr, const void *payload_ptr) {
316
    PrrtPacketDataPayload *data_payload = (PrrtPacketDataPayload *) payload_ptr;
Andreas Schmidt's avatar
Andreas Schmidt committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

    uint32_t *timestamp = (uint32_t *) buf_ptr;
    data_payload->timestamp = ntohl(*timestamp);
    buf_ptr += 4;

    uint16_t *group_round_trip_time = (uint16_t *) buf_ptr;
    data_payload->group_round_trip_time = ntohs(*group_round_trip_time);
    buf_ptr += 2;

    uint16_t *packet_timeout = (uint16_t *) buf_ptr;
    data_payload->packet_timeout = ntohs(*packet_timeout);
    buf_ptr += 2;

    uint16_t *decoding_timeout = (uint16_t *) buf_ptr;
    data_payload->decoding_timeout = ntohs(*decoding_timeout);
    buf_ptr += 2;

    uint16_t *feedback_timeout = (uint16_t *) buf_ptr;
    data_payload->feedback_timeout = ntohs(*feedback_timeout);
    buf_ptr += 2;
    return buf_ptr;
338
339
}

340
int PrrtPacket_destroy(PrrtPacket *packet_ptr) {
341
    if (packet_ptr->payload != NULL) {
342
343
344
        free(packet_ptr->payload);
    }
    free(packet_ptr);
345
346
347
    return 0;
}

348
// PACKET SPECIFIC CODE
349
int PrrtPacket_create_data_packet(PrrtPacket *packet_ptr, uint8_t priority, const void *data_ptr,
350
                                  uint32_t data_len, int seqno) {
351
    uint32_t payload_length = (uint32_t) (data_len + sizeof(PrrtPacketDataPayload));
352

353
    packet_ptr->type_priority = PACKET_TYPE_DATA << 4;
354
    packet_ptr->type_priority |= priority & 0x0F;
355
    packet_ptr->index = 17; // TODO: replace with sensible value
356
    packet_ptr->seqno = seqno;
357

358
    void *content_buf = malloc(sizeof(PrrtPacketDataPayload) + data_len);
359
    check_mem(content_buf);
360

361
    PrrtPacketDataPayload *source_payload = content_buf;
362
363

    struct timeval tv;
364
    gettimeofday(&tv, NULL);
365
366
    unsigned long time_in_micros = (unsigned long) (1000000 * tv.tv_sec + tv.tv_usec);

367
    source_payload->timestamp = (uint32_t) time_in_micros;
368
369
370
371
    source_payload->group_round_trip_time = 95; // TODO: payload->rtt = CURRENT ESTIMATE
    source_payload->packet_timeout = 110; // TODO: payload->packet_timeout = NOW + maximum delay
    source_payload->decoding_timeout = 150; // TODO: payload->decoding_timeout
    source_payload->feedback_timeout = 170; // TODO: payload->feedback_timer
372

373
    packet_ptr->payload = content_buf;
374
    memcpy(content_buf + sizeof(PrrtPacketDataPayload), data_ptr, data_len);
375
376
    packet_ptr->payload_len = payload_length;

377
378
    error:
        return -1;
379
380
}

381
PrrtPacket *PrrtPacket_create_redundancy_packet(uint8_t priority, void *data_ptr, uint32_t data_len,
382
383
                                                uint16_t seqno, uint8_t index, uint16_t base_seqno,
                                                PrrtCodingParams codingParams) {
384
385
    uint32_t payload_length = (uint32_t) (data_len + sizeof(PrrtPacketRedundancyPayload));

386
    PrrtPacket *packet_ptr = malloc(sizeof(PrrtPacket));
387
388
    check_mem(packet_ptr);

389
    packet_ptr->type_priority = PACKET_TYPE_REDUNDANCY << 4;
390
391
392
393
394
    packet_ptr->type_priority |= priority & 0x0F;
    packet_ptr->index = index;
    packet_ptr->seqno = seqno;

    void *content_buf = malloc(sizeof(PrrtPacketRedundancyPayload) + data_len);
395
    check_mem(content_buf);
396
397
398
399

    PrrtPacketRedundancyPayload *redundancy_payload = content_buf;

    redundancy_payload->base_seqno = base_seqno;
400
401
    redundancy_payload->k = codingParams.k;
    redundancy_payload->n = codingParams.n;
402
403
404
405
406
407

    packet_ptr->payload = content_buf;
    memcpy(content_buf + sizeof(PrrtPacketRedundancyPayload), data_ptr, data_len);
    packet_ptr->payload_len = payload_length;

    return packet_ptr;
408
409
410

    error:
        return NULL;
411
412
}

413
414
415
416
417
418
PrrtPacket *PrrtPacket_create_feedback_packet(uint8_t priority, uint8_t index, uint16_t seqno, uint32_t round_trip_time,
                                              uint32_t forward_trip_time, uint32_t packet_loss_rate, uint16_t gap,
                                              uint16_t ngap,
                                              uint16_t burst, uint16_t nburst, uint32_t bandwidth,
                                              uint32_t buffer_feedback) {
    PrrtPacket *packet_ptr = malloc(sizeof(PrrtPacket));
419
    check_mem(packet_ptr);
420
421
422
423
    packet_ptr->type_priority = PACKET_TYPE_FEEDBACK << 4;
    packet_ptr->type_priority |= priority & 0x0F;
    packet_ptr->index = index;
    packet_ptr->seqno = seqno;
424

425
    PrrtPacketFeedbackPayload *payload = malloc(sizeof(PrrtPacketFeedbackPayload));
426
    check_mem(payload);
427

428
429
    payload->group_round_trip_time = round_trip_time;
    payload->forward_trip_time = forward_trip_time;
430
    payload->packet_loss_rate = packet_loss_rate;
431
432
433
434
    payload->gap = gap;
    payload->ngap = ngap;
    payload->burst = burst;
    payload->nburst = nburst;
435
    payload->bandwidth_estimate = bandwidth;
436
    payload->buffer_feedback = buffer_feedback;
437

438
    packet_ptr->payload = (void *) payload;
439
    packet_ptr->payload_len = (uint32_t) (sizeof(PrrtPacketFeedbackPayload));
440

441
    return packet_ptr;
442
443
444

    error:
        return NULL;
445
}