packet.c 16 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
        printf("| %61s |\n", (char *) (packet_ptr->payload + PRRT_PACKET_DATA_HEADER_SIZE));
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
55
56
57
58
59
60
    } 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;
61
        printf("| %61u |\n", payload->group_round_trip_time);
62
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
63
        printf("| %61u |\n", payload->forward_trip_time);
64
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
65
        printf("| %61u |\n", payload->packet_loss_rate);
66
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
67
        printf("| %29u | %29u |\n", payload->gap, payload->ngap);
68
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
69
        printf("| %29u | %29u |\n", payload->burst, payload->nburst);
70
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
71
        printf("| %61u |\n", payload->bandwidth_estimate);
72
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
73
74
        printf("| %61u |\n", payload->buffer_feedback);
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
75
    } else {
76
77
        printf("| Unhandeled Type                                               |\n");
        printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
78
79
80
81
82
    }

    return 0;
}

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

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

88
89
    buf_ptr = encode_general_header(buf_ptr, packet_ptr);

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

    error:
107
    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

Andreas Schmidt's avatar
Andreas Schmidt committed
226
    void *payload_buffer = calloc(1, 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
        buf_ptr = decode_data_header(buf_ptr, payload_buffer);
234
        PrrtPacket_copy_buffer_to_payload(packet_ptr, buf_ptr, PRRT_PACKET_DATA_HEADER_SIZE);
235
    } else if (PrrtPacket_type(packet_ptr)) {
236
        buf_ptr = decode_redundancy_header(buf_ptr, payload_buffer);
237
        PrrtPacket_copy_buffer_to_payload(packet_ptr, buf_ptr, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
238
    } 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
        PrrtPacket_copy_buffer_to_payload(packet_ptr, buf_ptr, PRRT_PACKET_FEEDBACK_HEADER_SIZE);
Andreas Schmidt's avatar
Andreas Schmidt committed
241
    } else {
242
        printf("NOT IMPLEMENTED\n");
Andreas Schmidt's avatar
Andreas Schmidt committed
243
244
    }
    return 0;
245
246

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

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

    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;
}

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

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

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

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

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

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

Andreas Schmidt's avatar
Andreas Schmidt committed
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    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) {
315
    PrrtPacketDataPayload *data_payload = (PrrtPacketDataPayload *) payload_ptr;
Andreas Schmidt's avatar
Andreas Schmidt committed
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

    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;
337
338
}

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

347
int PrrtPacket_create_data_packet(PrrtPacket *packet_ptr, uint8_t priority, const void *data_ptr,
348
                                  uint32_t data_len, uint16_t seqno) {
349
    uint32_t payload_length = (uint32_t) (data_len + PRRT_PACKET_DATA_HEADER_SIZE);
350

351
    packet_ptr->type_priority = PACKET_TYPE_DATA << 4;
352
    packet_ptr->type_priority |= priority & 0x0F;
353
    packet_ptr->index = 0;
354
    packet_ptr->seqno = seqno;
355

356
    void *content_buf = calloc(1, payload_length);
357
    check_mem(content_buf);
358

359
    PrrtPacketDataPayload *source_payload = content_buf;
360
361

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

365
    source_payload->timestamp = (uint32_t) time_in_micros;
366
367
368
369
    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
370

371
372
    packet_ptr->payload = content_buf;
    packet_ptr->payload_len = payload_length;
373
    PrrtPacket_copy_buffer_to_payload(packet_ptr, data_ptr, PRRT_PACKET_DATA_HEADER_SIZE)
374

375
    error:
376
    return -1;
377
378
}

379
PrrtPacket *PrrtPacket_create_redundancy_packet(uint8_t priority, void *data_ptr, uint32_t data_len,
380
381
                                                uint16_t seqno, uint8_t index, uint16_t base_seqno,
                                                PrrtCodingParams codingParams) {
382
    uint32_t payload_length = (uint32_t) (data_len + PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
383

Andreas Schmidt's avatar
Andreas Schmidt committed
384
    PrrtPacket *packet_ptr = calloc(1, sizeof(PrrtPacket));
385
386
    check_mem(packet_ptr);

387
    packet_ptr->type_priority = PACKET_TYPE_REDUNDANCY << 4;
388
389
390
391
    packet_ptr->type_priority |= priority & 0x0F;
    packet_ptr->index = index;
    packet_ptr->seqno = seqno;

392
    void *content_buf = calloc(1, PRRT_PACKET_REDUNDANCY_HEADER_SIZE + data_len);
393
    check_mem(content_buf);
394
395
396
397

    PrrtPacketRedundancyPayload *redundancy_payload = content_buf;

    redundancy_payload->base_seqno = base_seqno;
398
399
    redundancy_payload->k = codingParams.k;
    redundancy_payload->n = codingParams.n;
400
401
402

    packet_ptr->payload = content_buf;
    packet_ptr->payload_len = payload_length;
403
    PrrtPacket_copy_buffer_to_payload(packet_ptr, data_ptr, PRRT_PACKET_REDUNDANCY_HEADER_SIZE);
404
405

    return packet_ptr;
406
407

    error:
408
    return NULL;
409
410
}

411
412
413
414
415
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) {
Andreas Schmidt's avatar
Andreas Schmidt committed
416
    PrrtPacket *packet_ptr = calloc(1, sizeof(PrrtPacket));
417
    check_mem(packet_ptr);
418
419
420
421
    packet_ptr->type_priority = PACKET_TYPE_FEEDBACK << 4;
    packet_ptr->type_priority |= priority & 0x0F;
    packet_ptr->index = index;
    packet_ptr->seqno = seqno;
422

423
    PrrtPacketFeedbackPayload *payload = calloc(1, PRRT_PACKET_FEEDBACK_HEADER_SIZE);
424
    check_mem(payload);
425

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

436
    packet_ptr->payload = (void *) payload;
437
    packet_ptr->payload_len = (uint32_t) (PRRT_PACKET_FEEDBACK_HEADER_SIZE);
438

439
    return packet_ptr;
440
441

    error:
442
    return NULL;
443
}