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