1 /** \file transport.c \brief Transport structures and functions
2 *
3 * $Author: peltotal $ $Date: 2007/02/28 08:58:00 $ $Revision: 1.43 $
4 *
5 * MAD-ALCLIB: Implementation of ALC/LCT protocols, Compact No-Code FEC,
6 * Simple XOR FEC, Reed-Solomon FEC, and RLC Congestion Control protocol.
7 * Copyright (c) 2003-2007 TUT - Tampere University of Technology
8 * main authors/contacts: jani.peltotalo@tut.fi and sami.peltotalo@tut.fi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * In addition, as a special exception, TUT - Tampere University of Technology
25 * gives permission to link the code of this program with the OpenSSL library (or
26 * with modified versions of OpenSSL that use the same license as OpenSSL), and
27 * distribute linked combinations including the two. You must obey the GNU
28 * General Public License in all respects for all of the code used other than
29 * OpenSSL. If you modify this file, you may extend this exception to your version
30 * of the file, but you are not obligated to do so. If you do not wish to do so,
31 * delete this exception statement from your version.
32 */
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <assert.h>
38 #include <string.h>
39
40 #ifdef _MSC_VER
41 #include <io.h>
42 #endif
43
44 #include "transport.h"
45
create_object(void)46 trans_obj_t* create_object(void) {
47
48 trans_obj_t *obj = NULL;
49
50 if (!(obj = (trans_obj_t*)calloc(1, sizeof(trans_obj_t)))) {
51 printf("Could not alloc memory for transport object!\n");
52 return NULL;
53 }
54
55 return obj;
56 }
57
create_block(void)58 trans_block_t* create_block(void) {
59
60 trans_block_t *block = NULL;
61
62 if (!(block = (trans_block_t*)calloc(1, sizeof(trans_block_t)))) {
63 printf("Could not alloc memory for transport block!\n");
64 return NULL;
65 }
66
67 return block;
68 }
69
create_units(unsigned int number)70 trans_unit_t* create_units(unsigned int number) {
71
72 trans_unit_t *unit = NULL;
73
74 if (!(unit = (trans_unit_t*)calloc(number, sizeof(trans_unit_t)))) {
75 printf("Could not alloc memory for %i transport units!\n", number);
76 }
77
78 return unit;
79 }
80
free_units(trans_block_t * tb)81 void free_units(trans_block_t *tb) {
82
83 trans_unit_t *tu = NULL;
84 trans_unit_t *next_tu = NULL;
85
86 next_tu = tb->unit_list;
87
88 while(next_tu != NULL) {
89 tu = next_tu;
90
91 if(tu->data != NULL) {
92 free(tu->data);
93 tu->data = NULL;
94 }
95
96 next_tu = tu->next;
97 free(tu);
98 }
99
100 tb->unit_list = NULL;
101 }
102
103 #ifdef USE_RETRIEVE_UNIT
104
retrieve_unit(alc_session_t * s,unsigned short es_len)105 trans_unit_t* retrieve_unit(alc_session_t *s, unsigned short es_len) {
106
107 trans_unit_container_t *container = NULL;
108 trans_unit_container_t *tmp;
109 trans_unit_container_t *start_search;
110
111 if(s->last_given != NULL) {
112 start_search = s->last_given->next;
113 } else {
114 start_search = s->unit_pool;
115 }
116
117 tmp = start_search;
118
119 while(tmp != NULL ) {
120 if(tmp->u.used == 0) {
121 if(tmp->u.len < es_len) {
122 continue;
123 }
124
125 tmp->u.used = 1;
126 s->last_given = tmp;
127 assert(tmp->u.data != NULL);
128 return &(tmp->u);
129 }
130 tmp = tmp->next;
131 }
132
133 tmp = s->unit_pool;
134 while(tmp != start_search) {
135 if(tmp->u.used == 0) {
136
137 if(tmp->u.len < es_len) {
138 continue;
139 }
140
141 tmp->u.used = 1;
142 s->last_given = tmp;
143 assert(tmp->u.data != NULL);
144 return &(tmp->u);
145 }
146 tmp = tmp->next;
147 }
148
149 if(!(container = (trans_unit_container_t*)calloc(1, sizeof(trans_unit_container_t)))) {
150 printf("Could not alloc memory for a transport unit container!\n");
151 return NULL;
152 }
153
154 container->next = s->unit_pool;
155 s->unit_pool = container;
156 container->u.used = 1;
157 s->last_given = s->unit_pool;
158
159 if(!(container->u.data = (char*)calloc(es_len, sizeof(char)))) {
160 printf("Could not alloc memory for transport unit's data!\n");
161 free(container);
162 return NULL;
163 }
164
165 return &(container->u);
166 }
167
free_units2(trans_block_t * tb)168 void free_units2(trans_block_t *tb) {
169 trans_unit_t *tu = NULL;
170 trans_unit_t *current_tu = NULL;
171
172 char *data = NULL;
173 unsigned short data_buffer_len;
174
175 current_tu = tb->unit_list;
176
177 while(current_tu != NULL) {
178 tu = current_tu;
179
180 /* backup the data pointer */
181
182 data = tu->data;
183 data_buffer_len = tu->len;
184
185 current_tu = tu->next;
186
187 memset(tu, 0, sizeof(trans_unit_t));
188
189 /* reinstall the backup */
190 tu->data = data;
191 tu->len = data_buffer_len;
192 }
193
194 tb->unit_list = NULL;
195 }
196
197 #endif
198
199 /*
200 void insert_object(trans_obj_t *to, alc_session_t *s, int type) {
201
202 trans_obj_t *tmp;
203
204 if(type == 0) {
205 tmp = s->fdt_list;
206 }
207 else {
208 tmp = s->obj_list;
209 }
210
211 if(tmp == NULL) {
212
213 if(type == 0) {
214 s->fdt_list = to;
215 }
216 else {
217 s->obj_list = to;
218 }
219 }
220 else {
221 for(;;) {
222 if(to->toi < tmp->toi) {
223
224 if(tmp->prev == NULL) {
225
226 to->next = tmp;
227 to->prev = tmp->prev;
228
229 tmp->prev = to;
230
231 if(type == 0) {
232 s->fdt_list = to;
233 }
234 else {
235 s->obj_list = to;
236 }
237
238 }
239 else {
240
241 to->next = tmp;
242 to->prev = tmp->prev;
243
244 tmp->prev->next = to;
245 tmp->prev = to;
246 }
247 break;
248 }
249
250 if(tmp->next == NULL) {
251
252 to->next = tmp->next;
253 to->prev = tmp;
254
255 tmp->next = to;
256 break;
257 }
258
259 tmp = tmp->next;
260 }
261 }
262 }*/
263
insert_object(trans_obj_t * to,alc_session_t * s,int type)264 void insert_object(trans_obj_t *to, alc_session_t *s, int type) {
265
266 trans_obj_t *tmp;
267
268 if(type == 0) {
269 tmp = s->fdt_list;
270 }
271 else {
272 tmp = s->obj_list;
273 }
274
275 if(tmp == NULL) {
276
277 if(type == 0) {
278 s->fdt_list = to;
279 }
280 else {
281 s->obj_list = to;
282 }
283 return;
284 }
285
286 for(;;) {
287 if(to->toi < tmp->toi) {
288
289 if(tmp->prev == NULL) {
290
291 to->next = tmp;
292 to->prev = tmp->prev;
293
294 tmp->prev = to;
295
296 if(type == 0) {
297 s->fdt_list = to;
298 }
299 else {
300 s->obj_list = to;
301 }
302
303 }
304 else {
305
306 to->next = tmp;
307 to->prev = tmp->prev;
308
309 tmp->prev->next = to;
310 tmp->prev = to;
311 }
312 break;
313 }
314
315 if(tmp->next == NULL) {
316
317 to->next = tmp->next;
318 to->prev = tmp;
319
320 tmp->next = to;
321 break;
322 }
323
324 tmp = tmp->next;
325 }
326 }
327
328 /*
329 * This function inserts transport unit to transport block.
330 *
331 * Params: trans_unit_t *tu: Pointer to transport unit to be inserted,
332 * trans_block_t *tb: Pointer to transport block,
333 * trans_obj_t *tu: Pointer to transport object.
334 *
335 * Return: int: 0 when transport unit is inserted, 1 when duplicated transport unit.
336 *
337 */
338 /*
339 int insert_unit(trans_unit_t *tu, trans_block_t *tb, trans_obj_t *to) {
340
341 trans_unit_t *tmp;
342 int retval = 0;
343
344 tmp = tb->unit_list;
345
346 if(tmp == NULL) {
347
348 to->rx_bytes += tu->len;
349
350 // for percentage counter
351 if(to->rx_bytes > to->len) {
352 to->rx_bytes = to->len;
353 }
354
355 tb->nb_of_rx_units++;
356
357 tb->unit_list = tu;
358 }
359 else {
360 for(;;) {
361 if(tu->esi < tmp->esi) {
362 //Delayed unit
363
364 to->rx_bytes += tu->len;
365
366 if(to->rx_bytes > to->len) {
367 to->rx_bytes = to->len;
368 }
369
370 tb->nb_of_rx_units++;
371
372 if(tmp->prev == NULL) {
373 tu->next = tmp;
374 tu->prev = tmp->prev;
375
376 tmp->prev = tu;
377
378 tb->unit_list = tu;
379 }
380 else {
381 tu->next = tmp;
382 tu->prev = tmp->prev;
383
384 tmp->prev->next = tu;
385 tmp->prev = tu;
386
387 }
388 break;
389 }
390 else if(tu->esi == tmp->esi) {
391 //Duplicated unit
392 retval = 1;
393 break;
394 }
395 if(tmp->next == NULL) {
396 // Last unit (normal order)
397
398 to->rx_bytes += tu->len;
399
400
401 if(to->rx_bytes > to->len) {
402 to->rx_bytes = to->len;
403 }
404
405 tb->nb_of_rx_units++;
406
407 tu->next = tmp->next;
408 tu->prev = tmp;
409
410 tmp->next = tu;
411 break;
412 }
413 tmp = tmp->next;
414 }
415 }
416
417 return retval;
418 }*/
419
insert_unit(trans_unit_t * tu,trans_block_t * tb,trans_obj_t * to)420 int insert_unit(trans_unit_t *tu, trans_block_t *tb, trans_obj_t *to) {
421
422 trans_unit_t *tmp;
423 int retval = 0;
424
425 tmp = tb->unit_list;
426
427 if(tmp == NULL) {
428
429 to->rx_bytes += tu->len;
430
431 // for percentage counter
432 if(to->rx_bytes > to->len) {
433 to->rx_bytes = to->len;
434 }
435
436 tb->nb_of_rx_units++;
437
438 tb->unit_list = tu;
439 return retval;
440 }
441
442 for(;;) {
443 if(tu->esi < tmp->esi) {
444 //Delayed unit
445
446 to->rx_bytes += tu->len;
447
448 if(to->rx_bytes > to->len) {
449 to->rx_bytes = to->len;
450 }
451
452 tb->nb_of_rx_units++;
453
454 if(tmp->prev == NULL) {
455 tu->next = tmp;
456 tu->prev = tmp->prev;
457
458 tmp->prev = tu;
459
460 tb->unit_list = tu;
461 }
462 else {
463 tu->next = tmp;
464 tu->prev = tmp->prev;
465
466 tmp->prev->next = tu;
467 tmp->prev = tu;
468
469 }
470 break;
471 }
472 else if(tu->esi == tmp->esi) {
473 //Duplicated unit
474 retval = 1;
475 break;
476 }
477 if(tmp->next == NULL) {
478 // Last unit (normal order)
479
480 to->rx_bytes += tu->len;
481
482
483 if(to->rx_bytes > to->len) {
484 to->rx_bytes = to->len;
485 }
486
487 tb->nb_of_rx_units++;
488
489 tu->next = tmp->next;
490 tu->prev = tmp;
491
492 tmp->next = tu;
493 break;
494 }
495 tmp = tmp->next;
496 }
497
498 return retval;
499 }
500
free_object(trans_obj_t * to,alc_session_t * s,int type)501 void free_object(trans_obj_t *to, alc_session_t *s, int type) {
502
503 #ifndef USE_RETRIEVE_UNIT
504 trans_block_t *tb;
505 trans_unit_t *tu;
506 trans_unit_t *next_tu;
507 unsigned int i;
508
509 for(i=0; i < to->bs->N; i++) {
510
511 tb = to->block_list+i;
512
513 next_tu = tb->unit_list;
514
515 while(next_tu != NULL) {
516 tu = next_tu;
517
518 if(tu->data != NULL) {
519 free(tu->data);
520 tu->data = NULL;
521 }
522
523 next_tu = tu->next;
524 free(tu);
525 }
526 }
527 #endif
528
529 free(to->bs);
530
531 if(to->next != NULL) {
532 to->next->prev = to->prev;
533 }
534 if(to->prev != NULL) {
535 to->prev->next = to->next;
536 }
537 if(((type == 0)&&(to == s->fdt_list))) {
538 s->fdt_list = to->next;
539 }
540 else if(((type == 1)&&(to == s->obj_list))) {
541 s->obj_list = to->next;
542 }
543
544 if(to->tmp_filename != NULL) {
545 free(to->tmp_filename);
546 to->tmp_filename = NULL;
547 if(type == 1) {
548 if(close(to->fd) == -1) {
549 printf("close failed, errno: %i\n", errno);
550 }
551 }
552 }
553
554 if(to->tmp_st_filename != NULL) {
555 if(type == 1) {
556 if(close(to->fd_st) == -1) {
557 printf("close failed, errno: %i\n", errno);
558 }
559 }
560 remove(to->tmp_st_filename);
561 free(to->tmp_st_filename);
562 to->tmp_st_filename = NULL;
563 }
564
565 if(to->block_list != NULL) {
566 free(to->block_list);
567 }
568
569 free(to);
570 }
571
572