1 /** \file null_fec.c \brief Compact No-Code FEC
2  *
3  *  $Author: peltotal $ $Date: 2007/02/28 08:58:00 $ $Revision: 1.33 $
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 <math.h>
37 #include <memory.h>
38 #include <assert.h>
39 
40 #include "null_fec.h"
41 
null_fec_encode_src_block(char * data,unsigned long long len,unsigned int sbn,unsigned short es_len)42 trans_block_t* null_fec_encode_src_block(char *data, unsigned long long len,
43 										 unsigned int sbn, unsigned short es_len) {
44 
45 	trans_block_t *tr_block;		/* transport block struct */
46 	trans_unit_t *tr_unit;			/* transport unit struct */
47 	unsigned int nb_of_units;		/* number of units */
48 	unsigned int i;					/* loop variables */
49 	unsigned long long data_left;
50 	char *ptr;						/* pointer to left data */
51 
52 	data_left = len;
53 
54 	nb_of_units = (unsigned int)ceil((double)(unsigned int)len / (double)es_len);
55 
56 	tr_block = create_block();
57 
58 	if(tr_block == NULL) {
59 		return tr_block;
60 	}
61 
62 	tr_unit = create_units(nb_of_units);
63 
64 	if(tr_unit == NULL) {
65 		free(tr_block);
66 		return NULL;
67 	}
68 
69 	ptr = data;
70 
71 	tr_block->unit_list = tr_unit;
72 	tr_block->sbn = sbn;
73 	tr_block->n = nb_of_units;
74 	tr_block->k = nb_of_units;
75 
76 	for(i = 0; i < nb_of_units; i++) {
77 		tr_unit->esi = i;
78 		tr_unit->len = data_left < es_len ? (unsigned short)data_left : es_len; /*min(eslen, data_left);*/
79 
80 		/* Alloc memory for TU data */
81 		if(!(tr_unit->data = (char*)calloc(tr_unit->len, sizeof(char)))) {
82 			printf("Could not alloc memory for transport unit's data!\n");
83 
84 			tr_unit = tr_block->unit_list;
85 
86 			while(tr_unit != NULL) {
87 				free(tr_unit->data);
88 				tr_unit++;
89 			}
90 
91 			free(tr_block->unit_list);
92 			free(tr_block);
93 			return NULL;
94 		}
95 
96 		memcpy(tr_unit->data, ptr, tr_unit->len);
97 
98 		ptr += tr_unit->len;
99 		data_left -= tr_unit->len;
100 		tr_unit++;
101 	}
102 
103 	return tr_block;
104 }
105 
null_fec_decode_src_block(trans_block_t * tr_block,unsigned long long * block_len,unsigned short eslen)106 char *null_fec_decode_src_block(trans_block_t *tr_block, unsigned long long *block_len,
107 								unsigned short eslen) {
108 
109 	char *buf = NULL; /* buffer where to construct the source block from data units */
110 
111     trans_unit_t *next_tu;
112     trans_unit_t *tu;
113 
114 	unsigned long long len;
115 	unsigned long long tmp;
116 
117     len = eslen*tr_block->k;
118 
119     /* Allocate memory for buf */
120     if(!(buf = (char*)calloc((unsigned int)(len + 1), sizeof(char)))) {
121         printf("Could not alloc memory for buf!\n");
122         return NULL;
123     }
124 
125     tmp = 0;
126 
127 	next_tu = tr_block->unit_list;
128 
129 	while(next_tu != NULL) {
130 
131         tu = next_tu;
132 
133 		/*if(tu->data == NULL) {
134 			printf("SB: %i, esi: %i\n", tr_block->sbn, tu->esi);
135 			fflush(stdout);
136 		}*/
137 
138         memcpy((buf+(unsigned int)tmp), tu->data, tu->len);
139 
140 #ifndef USE_RETRIEVE_UNIT
141         free(tu->data);
142         tu->data = NULL;
143 #endif
144 
145         tmp += tu->len;
146 
147         next_tu = tu->next;
148 	}
149 
150 	*block_len = len;
151 
152 	return buf;
153 }
154 
null_fec_decode_object(trans_obj_t * to,unsigned long long * data_len,alc_session_t * s)155 char *null_fec_decode_object(trans_obj_t *to, unsigned long long *data_len,
156 							 alc_session_t *s) {
157 
158 	char *object = NULL;
159 	char *block = NULL;
160 
161 	trans_block_t *tb;
162 
163 	unsigned long long to_data_left;
164 	unsigned long long len;
165 	unsigned long long block_len;
166 	unsigned long long position;
167 	unsigned int i;
168 
169 	/* Allocate memory for buf */
170 	if(!(object = (char*)calloc((unsigned int)(to->len+1), sizeof(char)))) {
171 		printf("Could not alloc memory for buf!\n");
172 		*data_len = 0;
173 		return NULL;
174 	}
175 
176 	to_data_left = to->len;
177 
178 	tb = to->block_list;
179 	position = 0;
180 
181 	for(i = 0; i < to->bs->N; i++) {
182 		block = null_fec_decode_src_block(tb, &block_len, (unsigned short)to->es_len);
183 
184 		/* the last packet of the last source block might be padded with zeros */
185 		len = to_data_left < block_len ? to_data_left : block_len;
186 
187 		assert (0 <= position);
188 		assert (position < to->len+1);
189 		assert (len <= (to->len-position));
190 
191 		memcpy(object+(unsigned int)position, block, (unsigned int)len);
192 		position += len;
193 		to_data_left -= len;
194 
195 		free(block);
196 		tb = to->block_list+(i+1);
197 	}
198 
199 	*data_len = to->len;
200 
201 	return object;
202 }
203