1 /** \file alc_rx.c \brief ALC level receiving
2  *
3  *  $Author: peltotal $ $Date: 2007/02/28 08:58:00 $ $Revision: 1.146 $
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 <string.h>
38 #include <time.h>
39 #include <fcntl.h>
40 #include <sys/stat.h>
41 #include <sys/types.h>
42 #include <math.h>
43 #include <assert.h>
44 
45 #ifdef _MSC_VER
46 #include <winsock2.h>
47 #include <process.h>
48 #include <io.h>
49 #else
50 #include <pthread.h>
51 #include <sys/socket.h>
52 #include <netdb.h>
53 #include <sys/time.h>
54 #endif
55 
56 #include "defines.h"
57 #include "alc_rx.h"
58 #include "alc_channel.h"
59 #include "mad_rlc.h"
60 #include "lct_hdr.h"
61 #include "null_fec.h"
62 #include "xor_fec.h"
63 #include "rs_fec.h"
64 #include "utils.h"
65 #include "transport.h"
66 #include "alc_list.h"
67 
68 /**
69  * This is a private function which parses and analyzes an ALC packet.
70  *
71  * @param data pointer to the ALC packet
72  * @param len length of packet
73  * @param ch pointer to the channel
74  *
75  * @return status of packet [WAITING_FDT = 5, OK = 4, EMPTY_PACKET = 3, HDR_ERROR = 2,
76  *                          MEM_ERROR = 1, DUP_PACKET = 0]
77  *
78  */
79 
analyze_packet(char * data,int len,alc_channel_t * ch)80 int analyze_packet(char *data, int len, alc_channel_t *ch) {
81 
82 	int retval = 0;
83 	int hdrlen = 0;			/* length of whole FLUTE/ALC/LCT header */
84 	int het = 0;
85 	int hel = 0;
86 	int exthdrlen = 0;
87 	unsigned int word = 0;
88 	short fec_enc_id = 0;
89 	unsigned long long ull = 0;
90 	unsigned long long block_len = 0;
91 	unsigned long long pos = 0;
92 
93 	/* LCT header upto CCI */
94 
95 	def_lct_hdr_t *def_lct_hdr = NULL;
96 
97 	/* remaining LCT header fields*/
98 
99 	unsigned long long tsi = 0; /* TSI */
100 	unsigned long long toi = 0; /* TOI */
101 
102 	/* EXT_FDT */
103 
104 	unsigned short flute_version = 0; /* V */
105 	int fdt_instance_id = 0; /* FDT Instance ID */
106 
107 	/* EXT_CENC */
108 
109 	unsigned char content_enc_algo = 0; /* CENC */
110 	unsigned short reserved = 0; /* Reserved */
111 
112 	/* EXT_FTI */
113 
114 	unsigned long long transfer_len = 0; /* L */
115 	unsigned char finite_field = 0; /* m */
116 	unsigned char nb_of_es_per_group = 0; /* G */
117 	unsigned short es_len = 0; /* E */
118 	unsigned short sb_len = 0;
119 	unsigned int max_sb_len = 0; /* B */
120 	unsigned short max_nb_of_es = 0; /* max_n */
121 	int fec_inst_id = 0; /* FEC Instance ID */
122 
123 	/* FEC Payload ID */
124 
125 	unsigned int sbn = 0;
126 	unsigned int esi = 0;
127 
128 	trans_obj_t *trans_obj = NULL;
129 	trans_block_t *trans_block = NULL;
130 	trans_unit_t *trans_unit = NULL;
131 	trans_unit_t *tu = NULL;
132 	trans_unit_t *next_tu = NULL;
133 	wanted_obj_t *wanted_obj = NULL;
134 
135 	char *buf = NULL;
136 
137 	char filename[MAX_PATH_LENGTH];
138 	double rx_percent = 0;
139 
140 	unsigned short j = 0;
141 	unsigned short nb_of_symbols = 0;
142 
143 	if(len < (int)(sizeof(def_lct_hdr_t))) {
144 		printf("analyze_packet: packet too short %d\n", len);
145 		fflush(stdout);
146 		return HDR_ERROR;
147 	}
148 
149 	def_lct_hdr = (def_lct_hdr_t*)data;
150 
151 	*(unsigned short*)def_lct_hdr = ntohs(*(unsigned short*)def_lct_hdr);
152 
153 	hdrlen += (int)(sizeof(def_lct_hdr_t));
154 
155 	if(def_lct_hdr->version != ALC_VERSION) {
156 		printf("ALC version: %i not supported!\n", def_lct_hdr->version);
157 		fflush(stdout);
158 		return HDR_ERROR;
159 	}
160 
161 	if(def_lct_hdr->reserved != 0) {
162 		printf("Reserved field not zero!\n");
163 		fflush(stdout);
164 		return HDR_ERROR;
165 	}
166 
167 	if(def_lct_hdr->flag_t != 0) {
168 		printf("Sender Current Time not supported!\n");
169 		fflush(stdout);
170 		return HDR_ERROR;
171 	}
172 
173 	if(def_lct_hdr->flag_r != 0) {
174 		printf("Expected Residual Time not supported!\n");
175 		fflush(stdout);
176 		return HDR_ERROR;
177 	}
178 
179 	if(def_lct_hdr->flag_b == 1) {
180 		/**** TODO ****/
181 	}
182 
183 	if(def_lct_hdr->flag_c != 0) {
184 		printf("Only 32 bits CCI-field supported!\n");
185 		fflush(stdout);
186 		return HDR_ERROR;
187 	}
188 	else {
189 		if(def_lct_hdr->cci != 0) {
190 
191 			if(ch->s->cc_id == RLC) {
192 
193 				retval = mad_rlc_analyze_cci(ch->s, (rlc_hdr_t*)(data + 4));
194 
195 				if(retval < 0) {
196 					return HDR_ERROR;
197 				}
198 			}
199 		}
200 	}
201 
202 	if(def_lct_hdr->flag_h == 1) {
203 
204 		if(def_lct_hdr->flag_s == 0) { /* TSI 16 bits */
205 			word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
206 			hdrlen += 4;
207 
208 			tsi = (word & 0xFFFF0000) >> 16;
209 
210 			if(tsi != ch->s->tsi) {
211 #ifdef _MSC_VER
212 				printf("Packet to wrong session: wrong TSI: %I64u\n", tsi);
213 #else
214 				printf("Packet to wrong session: wrong TSI: %llu\n", tsi);
215 #endif
216 				fflush(stdout);
217 				return HDR_ERROR;
218 			}
219 		}
220 		else if(def_lct_hdr->flag_s == 1) { /* TSI 48 bits */
221 
222 			ull = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
223 			tsi = ull << 16;
224 			hdrlen += 4;
225 
226 			word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
227 			hdrlen += 4;
228 
229 			tsi += (word & 0xFFFF0000) >> 16;
230 
231 			if(tsi != ch->s->tsi) {
232 #ifdef _MSC_VER
233 				printf("Packet to wrong session: wrong TSI: %I64u\n", tsi);
234 #else
235 				printf("Packet to wrong session: wrong TSI: %llu\n", tsi);
236 #endif
237 				fflush(stdout);
238 				return HDR_ERROR;
239 			}
240 		}
241 
242 		if(def_lct_hdr->flag_a == 1) {
243 			ch->s->state = SAFlagReceived;
244 		}
245 
246 		if(def_lct_hdr->flag_o == 0) { /* TOI 16 bits */
247 			toi = (word & 0x0000FFFF);
248 		}
249 		else if(def_lct_hdr->flag_o == 1) { /* TOI 48 bits */
250 
251 			ull = (word & 0x0000FFFF);
252 			toi = ull << 32;
253 
254 			toi += ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
255 			hdrlen += 4;
256 		}
257 		else {
258 			printf("Only 16, 32, 48 or 64 bits TOI-field supported!\n");
259 			fflush(stdout);
260 			return HDR_ERROR;
261 		}
262 		/*else if(def_lct_hdr->flag_o == 2) {
263 		}
264 		else if(def_lct_hdr->flag_o == 3) {
265 		}*/
266 	}
267 	else {
268 		if(def_lct_hdr->flag_s == 1) { /* TSI 32 bits */
269 			tsi = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
270 			hdrlen += 4;
271 
272 			if(tsi != ch->s->tsi) {
273 #ifdef _MSC_VER
274 				printf("Packet to wrong session: wrong TSI: %I64u\n", tsi);
275 #else
276 				printf("Packet to wrong session: wrong TSI: %llu\n", tsi);
277 #endif
278 				fflush(stdout);
279 				return HDR_ERROR;
280 			}
281 		}
282 		else {
283 			printf("Transport Session Identifier not present!\n");
284 			fflush(stdout);
285 			return HDR_ERROR;
286 		}
287 
288 		if(def_lct_hdr->flag_a == 1) {
289 			ch->s->state = SAFlagReceived;
290 		}
291 
292 		if(def_lct_hdr->flag_o == 0) { /* TOI 0 bits */
293 
294 			if(def_lct_hdr->flag_a != 1) {
295 				printf("Transport Object Identifier not present!\n");
296 				fflush(stdout);
297 				return HDR_ERROR;
298 			}
299 			else {
300 				return EMPTY_PACKET;
301 			}
302 		}
303 		else if(def_lct_hdr->flag_o == 1) { /* TOI 32 bits */
304 			toi = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
305 			hdrlen += 4;
306 		}
307 		else if(def_lct_hdr->flag_o == 2) { /* TOI 64 bits */
308 
309 			ull = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
310 			toi = ull << 32;
311 			hdrlen += 4;
312 
313 			toi += ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
314 			hdrlen += 4;
315 		}
316 		else {
317 			printf("Only 16, 32, 48 or 64 bits TOI-field supported!\n");
318 			fflush(stdout);
319 			return HDR_ERROR;
320 		}
321 		/*else if(def_lct_hdr->flag_o == 3) {
322 		}*/
323 	}
324 
325 	if(!toi == FDT_TOI) {
326 		wanted_obj = get_wanted_object(ch->s, toi);
327 
328 		if(wanted_obj == NULL) {
329 
330 			if(ch->s->rx_fdt_instance_list == NULL || ch->s->waiting_fdt_instance == TRUE) {
331 				return WAITING_FDT;
332 			}
333 			else {
334 				/*printf("Packet to not wanted toi: %i\n", toi);
335 				fflush(stdout);*/
336 				return HDR_ERROR;
337 			}
338 		}
339 
340 		es_len = wanted_obj->es_len;
341 		max_sb_len = wanted_obj->max_sb_len;
342 		max_nb_of_es = wanted_obj->max_nb_of_es;
343 		fec_enc_id = wanted_obj->fec_enc_id;
344 		transfer_len = wanted_obj->transfer_len;
345 		content_enc_algo = wanted_obj->content_enc_algo;
346 
347 		if(fec_enc_id == RS_FEC_ENC_ID) {
348 			finite_field = wanted_obj->finite_field;
349 			nb_of_es_per_group = wanted_obj->nb_of_es_per_group;
350 		}
351 		else {
352 			fec_inst_id = wanted_obj->fec_inst_id;
353 		}
354 	}
355 
356 	fec_enc_id = def_lct_hdr->codepoint;
357 
358 	if(!(fec_enc_id == COM_NO_C_FEC_ENC_ID || fec_enc_id == RS_FEC_ENC_ID ||
359 		fec_enc_id == SB_SYS_FEC_ENC_ID || fec_enc_id == SIMPLE_XOR_FEC_ENC_ID)) {
360 			printf("FEC Encoding ID: %i is not supported!\n", fec_enc_id);
361 			fflush(stdout);
362 			return HDR_ERROR;
363 	}
364 
365 	if(def_lct_hdr->hdr_len > (hdrlen >> 2)) {
366 
367 		/* LCT header extensions(EXT_FDT, EXT_CENC, EXT_FTI, EXT_AUTH, EXT_NOP)
368 		go through all possible EH */
369 
370 		exthdrlen = def_lct_hdr->hdr_len - (hdrlen >> 2);
371 
372 		while(exthdrlen > 0) {
373 
374 			word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
375 			hdrlen += 4;
376 			exthdrlen--;
377 
378 			het = (word & 0xFF000000) >> 24;
379 
380 			if(het < 128) {
381 				hel = (word & 0x00FF0000) >> 16;
382 			}
383 
384 			switch(het) {
385 
386 	  case EXT_FDT:
387 
388 		  flute_version = (word & 0x00F00000) >> 20;
389 		  fdt_instance_id = (word & 0x000FFFFF);
390 
391 		  if(flute_version != FLUTE_VERSION) {
392 			  printf("FLUTE version: %i is not supported\n", flute_version);
393 			  return HDR_ERROR;
394 		  }
395 
396 		  break;
397 
398 	  case EXT_CENC:
399 
400 		  content_enc_algo = (word & 0x00FF0000) >> 16;
401 		  reserved = (word & 0x0000FFFF);
402 
403 		  if(reserved != 0) {
404 			  printf("Bad CENC header extension!\n");
405 			  return HDR_ERROR;
406 		  }
407 
408 #ifdef USE_ZLIB
409 		  if((content_enc_algo != 0) && (content_enc_algo != ZLIB)) {
410 			  printf("Only NULL or ZLIB content encoding supported with FDT Instance!\n");
411 			  return HDR_ERROR;
412 		  }
413 #else
414 		  if(content_enc_algo != 0) {
415 			  printf("Only NULL content encoding supported with FDT Instance!\n");
416 			  return HDR_ERROR;
417 		  }
418 #endif
419 
420 		  break;
421 
422 	  case EXT_FTI:
423 
424 		  if(hel != 4) {
425 			  printf("Bad FTI header extension, length: %i\n", hel);
426 			  return HDR_ERROR;
427 		  }
428 
429 		  transfer_len = ((word & 0x0000FFFF) << 16);
430 
431 		  transfer_len += ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
432 		  hdrlen += 4;
433 		  exthdrlen--;
434 
435 		  word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
436 		  hdrlen += 4;
437 		  exthdrlen--;
438 
439 		  if(fec_enc_id == RS_FEC_ENC_ID) {
440 			  finite_field = (word & 0xFF000000) >> 24;
441 			  nb_of_es_per_group = (word & 0x00FF0000) >> 16;
442 
443 			  /*if(finite_field < 2 || finite_field >16) {
444 				  printf("Finite Field parameter: %i not supported!\n", finite_field);
445 				  return HDR_ERROR;
446 			  }*/
447 		  }
448 		  else {
449 			  fec_inst_id = ((word & 0xFFFF0000) >> 16);
450 
451 			  if((fec_enc_id == COM_NO_C_FEC_ENC_ID || fec_enc_id == SIMPLE_XOR_FEC_ENC_ID)
452 				  && fec_inst_id != 0) {
453 					  printf("Bad FTI header extension.\n");
454 					  return HDR_ERROR;
455 			  }
456 			  else if(fec_enc_id == SB_SYS_FEC_ENC_ID && fec_inst_id != REED_SOL_FEC_INST_ID) {
457 				  printf("FEC Encoding %i/%i is not supported!\n", fec_enc_id, fec_inst_id);
458 				  return HDR_ERROR;
459 			  }
460 		  }
461 
462 		  if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == SIMPLE_XOR_FEC_ENC_ID)
463 			  ||(fec_enc_id == SB_LB_E_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))){
464 
465 				  es_len = (word & 0x0000FFFF);
466 
467 				  max_sb_len = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
468 				  hdrlen += 4;
469 				  exthdrlen--;
470 		  }
471 		  else if(((fec_enc_id == RS_FEC_ENC_ID) || (fec_enc_id == SB_SYS_FEC_ENC_ID))) {
472 
473 			  es_len = (word & 0x0000FFFF);
474 
475 			  word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
476 
477 			  max_sb_len = ((word & 0xFFFF0000) >> 16);
478 			  max_nb_of_es = (word & 0x0000FFFF);
479 			  hdrlen += 4;
480 			  exthdrlen--;
481 		  }
482 		  break;
483 
484 	  case EXT_AUTH:
485 		  /* ignore */
486 		  hdrlen += (hel-1) << 2;
487 		  exthdrlen -= (hel-1);
488 		  break;
489 
490 	  case EXT_NOP:
491 		  /* ignore */
492 		  hdrlen += (hel-1) << 2;
493 		  exthdrlen -= (hel-1);
494 		  break;
495 
496 	  case EXT_TIME:
497 		  /* ignore */
498 		  hdrlen += (hel-1) << 2;
499 		  exthdrlen -= (hel-1);
500 		  break;
501 
502 	  default:
503 
504 		  printf("Unknown LCT Extension header, het: %i\n", het);
505 		  return HDR_ERROR;
506 		  break;
507 			}
508 		}
509 	}
510 
511 	if((hdrlen >> 2) != def_lct_hdr->hdr_len) {
512 		/* Wrong header length */
513 		printf("analyze_packet: packet header length %d, should be %d\n", (hdrlen >> 2),
514 			def_lct_hdr->hdr_len);
515 		return HDR_ERROR;
516 	}
517 
518 	/* Check if we have an empty packet without FEC Payload ID */
519 	if(hdrlen == len) {
520 		return EMPTY_PACKET;
521 	}
522 
523 	if(toi == 0) {
524 		if(is_received_instance(ch->s, fdt_instance_id)) {
525 			return DUP_PACKET;
526 		}
527 		else {
528 			ch->s->waiting_fdt_instance = TRUE;
529 		}
530 	}
531 
532 	if((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id ==  COM_FEC_ENC_ID)) {
533 
534 		if(len < hdrlen + 4) {
535 			printf("analyze_packet: packet too short %d\n", len);
536 			return HDR_ERROR;
537 		}
538 
539 		word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
540 		sbn = (word >> 16);
541 		esi = (word & 0xFFFF);
542 		hdrlen += 4;
543 	}
544 	else if(fec_enc_id == RS_FEC_ENC_ID) {
545 		word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
546 
547 		sbn = (word >> finite_field);
548 		esi = (word & ((1 << finite_field) - 1));
549 
550 		/* finite_field is not used furthermore, default value used in fec.c (#define GF_BITS  8 in fec.h) */
551 
552 		hdrlen += 4;
553 	}
554 	else if(((fec_enc_id == SB_LB_E_FEC_ENC_ID) || (fec_enc_id == SIMPLE_XOR_FEC_ENC_ID))) {
555 		if (len < hdrlen + 8) {
556 			printf("analyze_packet: packet too short %d\n", len);
557 			return HDR_ERROR;
558 		}
559 
560 		sbn = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
561 		hdrlen += 4;
562 		esi = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
563 		hdrlen += 4;
564 
565 	}
566 	else if(fec_enc_id == SB_SYS_FEC_ENC_ID) {
567 		if (len < hdrlen + 8) {
568 			printf("analyze_packet: packet too short %d\n", len);
569 			return HDR_ERROR;
570 		}
571 
572 		sbn = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
573 
574 		hdrlen += 4;
575 		word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen));
576 		sb_len = (word >> 16);
577 		esi = (word & 0xFFFF);
578 		hdrlen += 4;
579 	}
580 
581 	/* TODO: check if instance_id is set --> EXT_FDT header exists in packet */
582 
583 	if(len - hdrlen != 0) {
584 
585 		/* check if we have enough information */
586 
587 		if(((transfer_len == 0) || (fec_enc_id == -1) || ((fec_enc_id > 127) && (fec_inst_id == -1)) ||
588 			(es_len == 0) || (max_sb_len == 0))) {
589 #ifdef _MSC_VER
590 				printf("Not enough information to create Transport Object, TOI: %I64u\n", toi);
591 #else
592 				printf("Not enough information to create Transport Object, TOI: %llu\n", toi);
593 #endif
594 				fflush(stdout);
595 				return HDR_ERROR;
596 		}
597 
598 		if(fec_enc_id == RS_FEC_ENC_ID) {
599 			nb_of_symbols = nb_of_es_per_group;
600 		}
601 		else {
602 			/* Let's check how many symbols are in the packet */
603 			/* Encoding Symbol group length = len - hdrlen */
604 
605 			nb_of_symbols = (unsigned short)ceil((double)(len - hdrlen) / es_len);
606 		}
607 
608 		/* Now we have to go through each symbol */
609 
610 		for(j = 0; j < nb_of_symbols; j++) {
611 
612 #ifdef USE_RETRIEVE_UNIT
613 			/* Retrieve a transport unit from the session pool  */
614 			trans_unit = retrieve_unit(ch->s, es_len);
615 #else
616 			/* Create transport unit */
617 			trans_unit = create_units(1);
618 #endif
619 
620 			if(trans_unit == NULL) {
621 				return MEM_ERROR;
622 			}
623 
624 			trans_unit->esi = esi + j;
625 			trans_unit->len = es_len;
626 
627 #ifndef USE_RETRIEVE_UNIT
628 			/* Alloc memory for incoming TU data */
629 			if(!(trans_unit->data = (char*)calloc(es_len, sizeof(char)))) {
630 				printf("Could not alloc memory for transport unit's data!\n");
631 				return MEM_ERROR;
632 			}
633 #endif
634 
635 			memcpy(trans_unit->data, (data + hdrlen + j*es_len), trans_unit->len);
636 
637 			/* Check if object already exist */
638 			if(toi == FDT_TOI) {
639 				trans_obj = object_exist(fdt_instance_id, ch->s, 0);
640 			}
641 			else {
642 				trans_obj = object_exist(toi, ch->s, 1);
643 			}
644 
645 			if(trans_obj == NULL) {
646 
647 				trans_obj = create_object();
648 
649 				if(trans_obj == NULL) {
650 					return MEM_ERROR;
651 				}
652 
653 				if(toi == FDT_TOI) {
654 					trans_obj->toi = fdt_instance_id;
655 					trans_obj->content_enc_algo = content_enc_algo;
656 				}
657 				else {
658 					trans_obj->toi = toi;
659 
660 
661 					if(ch->s->rx_memory_mode == 1 || ch->s->rx_memory_mode == 2) {
662 
663 						memset(filename, 0, MAX_PATH_LENGTH);
664 
665 						if(content_enc_algo == 0) {
666 							sprintf(filename, "%s/%s", ch->s->base_dir, "object_XXXXXX");
667 							mktemp(filename);
668 						}
669 #ifdef USE_ZLIB
670 						else if(content_enc_algo == GZIP) {
671 							sprintf(filename, "%s/%s", ch->s->base_dir, "object_XXXXXX");
672 							mktemp(filename);
673 							strcat(filename, GZ_SUFFIX);
674 						}
675 #endif
676 						else if(content_enc_algo == PAD) {
677 							sprintf(filename, "%s/%s", ch->s->base_dir, "object_XXXXXX");
678 							mktemp(filename);
679 							strcat(filename, PAD_SUFFIX);
680 						}
681 
682 						/* Alloc memory for tmp_filename */
683 						if(!(trans_obj->tmp_filename = (char*)calloc(strlen(filename)+1, sizeof(char)))) {
684 							printf("Could not alloc memory for tmp_filename!\n");
685 							return MEM_ERROR;
686 						}
687 
688 						memcpy(trans_obj->tmp_filename, filename, strlen(filename));
689 
690 #ifdef _MSC_VER
691 						if((trans_obj->fd = open((const char*)trans_obj->tmp_filename,
692 							_O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC , _S_IWRITE)) < 0) {
693 #else
694 						if((trans_obj->fd = open(trans_obj->tmp_filename,
695 							O_WRONLY | O_CREAT | O_TRUNC , S_IRWXU)) < 0) {
696 #endif
697 								printf("Error: unable to open file %s\n", trans_obj->tmp_filename);
698 								fflush(stdout);
699 								return MEM_ERROR;
700 						}
701 					}
702 
703 
704 					if(ch->s->rx_memory_mode == 2) {
705 
706 						/* when receiver is in large file mode a tmp file is used to store the data symbols */
707 
708 						memset(filename, 0, MAX_PATH_LENGTH);
709 						sprintf(filename, "%s/%s", ch->s->base_dir, "st_XXXXXX");
710 						mktemp(filename);
711 
712 						/* Alloc memory for tmp_st_filename */
713 						if(!(trans_obj->tmp_st_filename = (char*)calloc(strlen(filename)+1, sizeof(char)))) {
714 							printf("Could not alloc memory for tmp_st_filename!\n");
715 							return MEM_ERROR;
716 						}
717 
718 						memcpy(trans_obj->tmp_st_filename, filename, strlen(filename));
719 
720 #ifdef _MSC_VER
721 						if((trans_obj->fd_st = open((const char*)trans_obj->tmp_st_filename,
722 							_O_RDWR | _O_CREAT | _O_BINARY | _O_TRUNC , _S_IREAD | _S_IWRITE)) < 0) {
723 #else
724 						if((trans_obj->fd_st = open(trans_obj->tmp_st_filename,
725 							O_RDWR | O_CREAT | O_TRUNC , S_IRWXU)) < 0) {
726 #endif
727 								printf("Error: unable to open file %s\n", trans_obj->tmp_st_filename);
728 								fflush(stdout);
729 								return MEM_ERROR;
730 						}
731 					}
732 				}
733 
734 				trans_obj->len = transfer_len;
735 				trans_obj->fec_enc_id = (unsigned char)fec_enc_id;
736 				trans_obj->fec_inst_id = (unsigned short)fec_inst_id;
737 				trans_obj->es_len = es_len;
738 				trans_obj->max_sb_len = max_sb_len;
739 
740 				/* Let's calculate the blocking structure for this object */
741 
742 				trans_obj->bs = compute_blocking_structure(transfer_len, max_sb_len, es_len);
743 
744 				if(!(trans_obj->block_list = (trans_block_t*)calloc(trans_obj->bs->N, sizeof(trans_block_t)))) {
745 					printf("Could not alloc memory for transport block list!\n");
746 					return MEM_ERROR;
747 				}
748 
749 				if(toi == FDT_TOI) {
750 					insert_object(trans_obj, ch->s, 0);
751 				}
752 				else {
753 					insert_object(trans_obj, ch->s, 1);
754 				}
755 			}
756 
757 			trans_block = trans_obj->block_list+sbn;
758 
759 			if(trans_block->nb_of_rx_units == 0) {
760 				trans_block->sbn = sbn;
761 
762 				if(fec_enc_id == COM_NO_C_FEC_ENC_ID) {
763 
764 					if(sbn < trans_obj->bs->I) {
765 						trans_block->k = trans_obj->bs->A_large;
766 					}
767 					else {
768 						trans_block->k = trans_obj->bs->A_small;
769 					}
770 				}
771 				else if(fec_enc_id == SB_SYS_FEC_ENC_ID) {
772 
773 					trans_block->k = sb_len;
774 					trans_block->max_k = max_sb_len;
775 					trans_block->max_n = max_nb_of_es;
776 				}
777 				else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
778 
779 					if(sbn < trans_obj->bs->I) {
780 						trans_block->k = trans_obj->bs->A_large;
781 					}
782 					else {
783 						trans_block->k = trans_obj->bs->A_small;
784 					}
785 
786 					trans_block->max_k = max_sb_len;
787 				}
788 				else if(fec_enc_id == RS_FEC_ENC_ID) {
789 
790 					if(sbn < trans_obj->bs->I) {
791 						trans_block->k = trans_obj->bs->A_large;
792 					}
793 					else {
794 						trans_block->k = trans_obj->bs->A_small;
795 					}
796 
797 					trans_block->max_k = max_sb_len;
798 					trans_block->max_n = max_nb_of_es;
799 
800 					/*trans_block->finite_field = finite_field;*/
801 				}
802 			}
803 
804 			if(!block_ready_to_decode(trans_block)) {
805 
806 				if(insert_unit(trans_unit, trans_block, trans_obj) != 1) {
807 
808 					if(toi == FDT_TOI || ch->s->rx_memory_mode == 0) {
809 
810 						if(block_ready_to_decode(trans_block)) {
811 							trans_obj->nb_of_ready_blocks++;
812 						}
813 					}
814 
815 					/* if large file mode data symbol is stored in the tmp file */
816 					if(toi != FDT_TOI && ch->s->rx_memory_mode == 2) {
817 
818 #ifdef _MSC_VER
819 						trans_unit->offset = _lseeki64(trans_obj->fd_st, 0, SEEK_END);
820 #else
821 						trans_unit->offset = lseek(trans_obj->fd_st, 0, SEEK_END);
822 #endif
823 						if(trans_unit->offset == -1) {
824 #ifdef _MSC_VER
825 							printf("lseek error, toi: %I64u\n", toi);
826 #else
827 							printf("lseek error, toi: %llu\n", toi);
828 #endif
829 							fflush(stdout);
830 							set_session_state(ch->s->s_id, SExiting);
831 							return MEM_ERROR;
832 						}
833 
834 						if(write(trans_obj->fd_st, trans_unit->data, (unsigned int)trans_unit->len) == -1) {
835 #ifdef _MSC_VER
836 							printf("write error, toi: %I64u, sbn: %i\n", toi, sbn);
837 #else
838 							printf("write error, toi: %llu, sbn: %i\n", toi, sbn);
839 #endif
840 							fflush(stdout);
841 							set_session_state(ch->s->s_id, SExiting);
842 							return MEM_ERROR;
843 						}
844 
845 #ifndef USE_RETRIEVE_UNIT
846 						free(trans_unit->data);
847 						trans_unit->data = NULL;
848 #endif
849 					}
850 
851 					if(((toi == FDT_TOI && ch->s->verbosity == 4) || (toi != FDT_TOI && ch->s->verbosity > 1))) {
852 
853 						rx_percent = (double)((double)100 *
854 							((double)(long long)trans_obj->rx_bytes/(double)(long long)trans_obj->len));
855 
856 						if(((rx_percent >= (trans_obj->last_print_rx_percent + 1)) || (rx_percent == 100))) {
857 							trans_obj->last_print_rx_percent = rx_percent;
858 							printf("%.2f%% of object received (TOI=%llu LAYERS=%i)\n", rx_percent,
859 								toi, ch->s->nb_channel);
860 							fflush(stdout);
861 						}
862 					}
863 				}
864 				else {
865 
866 #ifdef USE_RETRIEVE_UNIT
867 					trans_unit->used = 0;
868 #else
869 					free(trans_unit->data);
870 					free(trans_unit);
871 #endif
872 					return DUP_PACKET;
873 				}
874 			}
875 			else {
876 
877 #ifdef USE_RETRIEVE_UNIT
878 				trans_unit->used = 0;
879 #else
880 				free(trans_unit->data);
881 				free(trans_unit);
882 #endif
883 				return DUP_PACKET;
884 			}
885 
886 			if(toi != FDT_TOI) {
887 
888 				if(ch->s->rx_memory_mode == 1 || ch->s->rx_memory_mode == 2) {
889 
890 					if(block_ready_to_decode(trans_block)) {
891 
892 						if(ch->s->rx_memory_mode == 2){
893 
894 							/* We have to restore the data symbols to trans_units from the symbol store tmp file */
895 
896 							next_tu = trans_block->unit_list;
897 
898 							while(next_tu != NULL) {
899 
900 								tu = next_tu;
901 
902 #ifdef _MSC_VER
903 								if(_lseeki64(trans_obj->fd_st, tu->offset, SEEK_SET) == -1) {
904 #else
905 								if(lseek(trans_obj->fd_st, tu->offset, SEEK_SET) == -1) {
906 #endif
907 
908 #ifdef _MSC_VER
909 									printf("lseek error, toi: %I64u\n", toi);
910 #else
911 									printf("alc_rx.c line 1035 lseek error, toi: %llu\n", toi);
912 #endif
913 									fflush(stdout);
914 									set_session_state(ch->s->s_id, SExiting);
915 									return MEM_ERROR;
916 								}
917 
918 								/* let's copy the data symbols from the tmp file to the memory */
919 
920 								/* Alloc memory for restoring data symbol */
921 
922 								if(!(tu->data = (char*)calloc(tu->len, sizeof(char)))) {
923 									printf("Could not alloc memory for transport unit's data!\n");
924 									return MEM_ERROR;
925 								}
926 
927 								if(read(trans_obj->fd_st, tu->data, tu->len) == -1) {
928 #ifdef _MSC_VER
929 									printf("read error, toi: %I64u, sbn: %i\n", toi, sbn);
930 #else
931 									printf("read error, toi: %llu, sbn: %i\n", toi, sbn);
932 #endif
933 									fflush(stdout);
934 									set_session_state(ch->s->s_id, SExiting);
935 									return MEM_ERROR;
936 								}
937 
938 								next_tu = tu->next;
939 							}
940 						}
941 
942 						/* decode the block and save data to the tmp file */
943 
944 						if(fec_enc_id == COM_NO_C_FEC_ENC_ID) {
945 							buf = null_fec_decode_src_block(trans_block, &block_len, es_len);
946 						}
947 						else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
948 							buf = xor_fec_decode_src_block(trans_block, &block_len, es_len);
949 						}
950 						else if(fec_enc_id == RS_FEC_ENC_ID) {
951 							buf = rs_fec_decode_src_block(trans_block, &block_len, es_len);
952 						}
953 						else if(fec_enc_id == SB_SYS_FEC_ENC_ID && fec_inst_id == REED_SOL_FEC_INST_ID) {
954 							buf = rs_fec_decode_src_block(trans_block, &block_len, es_len);
955 						}
956 
957 						if(buf == NULL) {
958 							return MEM_ERROR;
959 						}
960 
961 						/* We have to check if there is padding in the last source symbol of the last source block */
962 
963 						if(trans_block->sbn == ((trans_obj->bs->N) - 1)) {
964 							block_len = (trans_obj->len - (es_len * (trans_obj->bs->I * trans_obj->bs->A_large +
965 								(trans_obj->bs->N - trans_obj->bs->I -1) * trans_obj->bs->A_small)));
966 						}
967 
968 						if(trans_block->sbn < trans_obj->bs->I) {
969 							pos = ( (unsigned long long)trans_block->sbn * (unsigned long long)trans_obj->bs->A_large * (unsigned long long)es_len );
970 						}
971 						else {
972 							pos = ( ( ( (unsigned long long)trans_obj->bs->I * (unsigned long long)trans_obj->bs->A_large ) +
973 								( (unsigned long long)trans_block->sbn - (unsigned long long)trans_obj->bs->I )  *
974 								(unsigned long long)trans_obj->bs->A_small ) * (unsigned long long)es_len );
975 						}
976 
977 						/* set correct position */
978 
979 #ifdef _MSC_VER
980 						if(_lseeki64(trans_obj->fd, pos, SEEK_SET) == -1) {
981 #else
982 						if(lseek(trans_obj->fd, pos, SEEK_SET) == -1) {
983 #endif
984 
985 #ifdef _MSC_VER
986 							printf("lseek error, toi: %I64u\n", toi);
987 #else
988 							printf("alc_rx.c line 1111 lseek error, toi: %llu\n", toi);
989 #endif
990 							fflush(stdout);
991 							free(buf);
992 							set_session_state(ch->s->s_id, SExiting);
993 							return MEM_ERROR;
994 						}
995 
996 						if(write(trans_obj->fd, buf, (unsigned int)block_len) == -1) {
997 #ifdef _MSC_VER
998 							printf("write error, toi: %I64u, sbn: %i\n", toi, sbn);
999 #else
1000 							printf("write error, toi: %llu, sbn: %i\n", toi, sbn);
1001 #endif
1002 							fflush(stdout);
1003 							free(buf);
1004 							set_session_state(ch->s->s_id, SExiting);
1005 							return MEM_ERROR;
1006 						}
1007 
1008 						trans_obj->nb_of_ready_blocks++;
1009 
1010 						free(buf);
1011 
1012 #ifdef USE_RETRIEVE_UNIT
1013 						free_units2(trans_block);
1014 #else
1015 						free_units(trans_block);
1016 #endif
1017 
1018 						if(ch->s->verbosity > 2) {
1019 #ifdef _MSC_VER
1020 							printf("%u/%u Source Blocks decoded (TOI=%I64u SBN=%u)\n", trans_obj->nb_of_ready_blocks, trans_obj->bs->N, toi, sbn);
1021 							fflush(stdout);
1022 #else
1023 							printf("%u/%u Source Blocks decoded (TOI=%llu SBN=%u)\n", trans_obj->nb_of_ready_blocks, trans_obj->bs->N, toi, sbn);
1024 							fflush(stdout);
1025 #endif
1026 						}
1027 					}
1028 				}
1029 			}
1030 		} /* End of "for(j = 0; j < nb_of_symbols; j++) {" */
1031 	}
1032 	else { /* We have an empty packet with FEC Payload ID */
1033 		return EMPTY_PACKET;
1034 	}
1035 
1036 	return OK;
1037 }
1038 
1039 /**
1040  * This is a private function which receives unit(s) from the session's channels.
1041  *
1042  * @param s pointer to the session
1043  *
1044  * @return number of correct packets received from ALC session, or 0 when state is SClosed or no packets,
1045  * or -1 in error cases, or -2 when state is SExiting
1046  *
1047  */
1048 
1049 int recv_packet(alc_session_t *s) {
1050 
1051   char recvbuf[MAX_PACKET_LENGTH];
1052   int recvlen;
1053   int i;
1054   int retval;
1055   int recv_pkts = 0;
1056   alc_channel_t *ch;
1057   struct sockaddr_storage from;
1058 
1059   double loss_prob;
1060 
1061   alc_rcv_container_t *container;
1062   int my_list_not_empty = 0;
1063 
1064 #ifdef _MSC_VER
1065   int fromlen;
1066 #else
1067   socklen_t fromlen;
1068 #endif
1069 
1070   time_t systime;
1071   unsigned long long curr_time;
1072 
1073   memset(recvbuf, 0, MAX_PACKET_LENGTH);
1074 
1075   for(i = 0; i < s->nb_channel; i++) {
1076     ch = s->ch_list[i];
1077 
1078     if(ch->receiving_list != NULL) {
1079       if(!is_empty(ch->receiving_list)) {
1080 	++my_list_not_empty;
1081 	break;
1082       }
1083     }
1084   }
1085 
1086   if(my_list_not_empty == 0) {
1087 
1088     if(s->stoptime != 0) {
1089       time(&systime);
1090       curr_time = systime + 2208988800U;
1091 
1092       if(curr_time >= s->stoptime) {
1093 	s->state = SExiting;
1094 	return -2;
1095       }
1096     }
1097 
1098 #ifdef _MSC_VER
1099     Sleep(500);
1100 #else
1101     usleep(500000);
1102 #endif
1103 
1104     if(s->state == SAFlagReceived) {
1105       s->state = STxStopped;
1106     }
1107 
1108     return 0;
1109   }
1110 
1111   for(i = 0; i < s->nb_channel; i++) {
1112     ch = s->ch_list[i];
1113 
1114     if(!is_empty(ch->receiving_list)) {
1115       assert(ch->rx_socket_thread_id != 0);
1116 
1117       container = (alc_rcv_container_t*)pop_front(ch->receiving_list);
1118 
1119       assert(container != NULL);
1120 
1121       recvlen = container->recvlen;
1122       from = container->from;
1123       fromlen = container->fromlen;
1124       memcpy(recvbuf, container->recvbuf, MAX_PACKET_LENGTH);
1125 
1126       if(recvlen < 0) {
1127 
1128 	free(container);
1129 	container = NULL;
1130 
1131 	if(s->state == SExiting) {
1132 	  printf("recv_packet() SExiting\n");
1133 	  fflush(stdout);
1134 	  return -2;
1135 	}
1136 	else if(s->state == SClosed) {
1137 	  printf("recv_packet() SClosed\n");
1138 	  fflush(stdout);
1139 	  return 0;
1140 	}
1141 	else {
1142 #ifdef _MSC_VER
1143 	  printf("recvfrom failed: %d\n", WSAGetLastError());
1144 	  fflush(stdout);
1145 #else
1146 	  printf("recvfrom failed: %d\n", errno);
1147 #endif
1148 	  return -1;
1149 	}
1150       }
1151 
1152       loss_prob = 0;
1153 
1154       if(ch->s->simul_losses) {
1155 	if(ch->previous_lost == TRUE) {
1156 	  loss_prob = ch->s->loss_ratio2;
1157 	}
1158 	else {
1159 	  loss_prob = ch->s->loss_ratio1;
1160 	}
1161       }
1162 
1163       if(!randomloss(loss_prob)) {
1164 
1165 	retval = analyze_packet(recvbuf, recvlen, ch);
1166 
1167 	if(ch->s->cc_id == RLC) {
1168 
1169 	  if(((ch->s->rlc->drop_highest_layer) && (ch->s->nb_channel != 1))) {
1170 
1171 	    ch->s->rlc->drop_highest_layer = FALSE;
1172 	    close_alc_channel(ch->s->ch_list[ch->s->nb_channel - 1], ch->s);
1173 	  }
1174 	}
1175 
1176 	if(retval == WAITING_FDT) {
1177 	  push_front(ch->receiving_list, (void*)container);
1178 	}
1179 	else {
1180 	  free(container);
1181 	  container = NULL;
1182 
1183 	  if(retval == HDR_ERROR) {
1184 	    continue;
1185 	  }
1186 	  else if(retval == DUP_PACKET) {
1187 	    continue;
1188 	  }
1189 	  else if(retval == MEM_ERROR) {
1190 	    return -1;
1191 	  }
1192 
1193 	  recv_pkts++;
1194 
1195 	  ch->previous_lost = FALSE;
1196 	}
1197       }
1198       else {
1199 	ch->previous_lost = TRUE;
1200       }
1201     }
1202   }
1203   return recv_pkts;
1204 }
1205 
1206 void* rx_socket_thread(void *ch) {
1207 
1208   alc_channel_t *channel;
1209   alc_rcv_container_t *container;
1210   fd_set read_set;
1211   struct timeval time_out;
1212   char hostname[100];
1213   int retval;
1214 
1215   channel = (alc_channel_t *)ch;
1216 
1217   while(channel->s->state == SActive) {
1218 
1219     time_out.tv_sec = 1;
1220     time_out.tv_usec = 0;
1221 
1222     FD_ZERO(&read_set);
1223     FD_SET(channel->rx_sock, &read_set);
1224 
1225     retval = select((int)channel->rx_sock + 1, &read_set, 0, 0, &time_out);
1226 
1227     if(retval > 0) {
1228       if(!(container = (alc_rcv_container_t*)calloc(1, sizeof(alc_rcv_container_t)))) {
1229 	printf("Could not alloc memory for container!\n");
1230 	continue;
1231       }
1232 
1233       if(channel->s->addr_family == PF_INET) {
1234 	container->fromlen = sizeof(struct sockaddr_in);
1235       }
1236       else if(channel->s->addr_family == PF_INET6) {
1237 	container->fromlen = sizeof(struct sockaddr_in6);
1238       }
1239 
1240       container->recvlen = recvfrom(channel->rx_sock, container->recvbuf, MAX_PACKET_LENGTH,
1241 				    0, (struct sockaddr*)&(container->from), &(container->fromlen));
1242 
1243 #ifdef _MSC_VER
1244       if(container->recvlen == -1) {
1245 	/* Some times when you quit program very quick after starting in Windows, select returns
1246 	   1, but there is nothing to be stored to the queue. Continue is for avoiding error */
1247 	continue;
1248       }
1249 #endif
1250 
1251       getnameinfo((struct sockaddr*)&(container->from), container->fromlen,
1252 		  hostname, sizeof(hostname), NULL, 0, NI_NUMERICHOST);
1253 
1254       if(strcmp(channel->s->src_addr, "") != 0) {
1255 	if(strcmp(hostname, channel->s->src_addr) != 0) {
1256 	  printf("Packet to wrong session: wrong source: %s\n", hostname);
1257 	  fflush(stdout);
1258 	  continue;
1259 	}
1260       }
1261 
1262       push_back(channel->receiving_list, (void*)container);
1263 
1264       if(strcmp(channel->s->src_addr, "") == 0) {
1265 	if(channel->s->verbosity > 0) {
1266 	  printf("Locked to source: %s\n", hostname);
1267 	  fflush(stdout);
1268 	}
1269 
1270 	memcpy(channel->s->src_addr, hostname, strlen(hostname));
1271       }
1272     }
1273     else {
1274       continue;
1275     }
1276   }
1277 
1278 #ifdef _MSC_VER
1279   _endthread();
1280 #else
1281   pthread_exit(0);
1282 #endif
1283 
1284   return NULL;
1285 }
1286 
1287 void join_rx_socket_thread(alc_channel_t *ch) {
1288 
1289 #ifndef _MSC_VER
1290   int join_retval;
1291 #endif
1292 
1293   if(ch != NULL) {
1294 #ifdef _MSC_VER
1295     WaitForSingleObject(ch->handle_rx_socket_thread, INFINITE);
1296     CloseHandle(ch->handle_rx_socket_thread);
1297 #else
1298     join_retval = pthread_join(ch->rx_socket_thread_id, NULL);
1299     assert(join_retval == 0);
1300     pthread_detach(ch->rx_socket_thread_id);
1301 #endif
1302   }
1303 }
1304 
1305 void* rx_thread(void *s) {
1306 
1307   alc_session_t *session;
1308   int retval = 0;
1309 
1310   srand((unsigned)time(NULL));
1311 
1312   session = (alc_session_t *)s;
1313 
1314   while(session->state == SActive || session->state == SAFlagReceived) {
1315 
1316     if(session->nb_channel != 0) {
1317       retval = recv_packet(session);
1318     }
1319     else {
1320 #ifdef _MSC_VER
1321       Sleep(1);
1322 #else
1323       usleep(1000);
1324 #endif
1325     }
1326   }
1327 
1328 #ifdef _MSC_VER
1329   _endthread();
1330 #else
1331   pthread_exit(0);
1332 #endif
1333 
1334   return NULL;
1335 }
1336 
1337 char* alc_recv(int s_id, unsigned long long toi, unsigned long long *data_len, int *retval) {
1338 
1339 	BOOL obj_completed = FALSE;
1340 	alc_session_t *s;
1341 	char *buf = NULL; /* Buffer where to construct the object from data units */
1342 	trans_obj_t *to;
1343 	int object_exists = 0;
1344 
1345 	s = get_alc_session(s_id);
1346 
1347 	while(!obj_completed) {
1348 
1349 		if(s->state == SExiting) {
1350 			/*printf("alc_recv() SExiting\n");
1351 			fflush(stdout);*/
1352 			*retval = -2;
1353 			return NULL;
1354 		}
1355 		else if(s->state == SClosed) {
1356 			/*printf("alc_recv() SClosed\n");
1357 			fflush(stdout);*/
1358 			*retval = 0;
1359 			return NULL;
1360 		}
1361 
1362 		to = s->obj_list;
1363 
1364 		if(!object_exists) {
1365 
1366 			while(to != NULL) {
1367 				if(to->toi == toi) {
1368 					object_exists = 1;
1369 					break;
1370 				}
1371 				to = to->next;
1372 			}
1373 
1374 			if(to == NULL) {
1375 				continue;
1376 			}
1377 		}
1378 
1379 		obj_completed = object_completed(to);
1380 
1381 		if(((s->state == STxStopped) && (!obj_completed))) {
1382 			/*printf("alc_recv() STxStopped, toi: %i\n", toi);
1383 			fflush(stdout);*/
1384 			*retval = -3;
1385 			return NULL;
1386 		}
1387 
1388 #ifdef _MSC_VER
1389 		Sleep(1);
1390 #else
1391 		usleep(1000);
1392 #endif
1393 	}
1394 	printf("\n");
1395 
1396 	remove_wanted_object(s_id, toi);
1397 
1398 	/* Parse data from object to data buffer, return buffer and buffer length */
1399 
1400 	to = object_exist(toi, s, 1);
1401 
1402 	if(to->fec_enc_id == COM_NO_C_FEC_ENC_ID) {
1403 		buf = null_fec_decode_object(to, data_len, s);
1404 	}
1405 	else if(to->fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
1406 		buf = xor_fec_decode_object(to, data_len, s);
1407 	}
1408 	else if(to->fec_enc_id == RS_FEC_ENC_ID) {
1409 		buf = rs_fec_decode_object(to, data_len, s);
1410 	}
1411 	else if(to->fec_enc_id == SB_SYS_FEC_ENC_ID && to->fec_inst_id == REED_SOL_FEC_INST_ID) {
1412 		buf = rs_fec_decode_object(to, data_len, s);
1413 	}
1414 
1415 	if(buf == NULL) {
1416 		*retval = -1;
1417 	}
1418 
1419 	free_object(to, s, 1);
1420 	return buf;
1421 }
1422 
1423 char* alc_recv2(int s_id, unsigned long long *toi, unsigned long long *data_len, int *retval) {
1424 
1425 	BOOL obj_completed = FALSE;
1426 	alc_session_t *s;
1427 
1428 	unsigned long long tmp_toi = 0;
1429 
1430 	char *buf = NULL; /* Buffer where to construct the object from data units */
1431 	trans_obj_t *to;
1432 
1433 	s = get_alc_session(s_id);
1434 
1435 	while(1) {
1436 
1437 		to = s->obj_list;
1438 
1439 		if(s->state == SExiting) {
1440 			/*printf("alc_recv2() SExiting\n");
1441 			fflush(stdout);*/
1442 			*retval = -2;
1443 			return NULL;
1444 		}
1445 		else if(s->state == SClosed) {
1446 			/*printf("alc_recv2() SClosed\n");
1447 			fflush(stdout);*/
1448 			*retval = 0;
1449 			return NULL;
1450 		}
1451 		else if(((s->state == STxStopped) && (to == NULL))) {
1452 			/*printf("alc_recv2() STxStopped\n");
1453 			fflush(stdout);*/
1454 			*retval = -3;
1455 			return NULL;
1456 		}
1457 
1458 		while(to != NULL) {
1459 
1460 			if(s->state == SExiting) {
1461 				/*printf("alc_recv2() SExiting\n");
1462 				fflush(stdout);*/
1463 				*retval = -2;
1464 				return NULL;
1465 			}
1466 			else if(s->state == SClosed) {
1467 				/*printf("alc_recv2() SClosed\n");
1468 				fflush(stdout);*/
1469 				*retval = 0;
1470 				return NULL;
1471 			}
1472 
1473 			obj_completed = object_completed(to);
1474 
1475 			if(obj_completed) {
1476 				tmp_toi = to->toi;
1477 				break;
1478 			}
1479 
1480 			if(((s->state == STxStopped) && (!obj_completed))) {
1481 				/*printf("alc_recv2() STxStopped\n");
1482 				fflush(stdout);*/
1483 				*retval = -3;
1484 				return NULL;
1485 			}
1486 
1487 			to = to->next;
1488 		}
1489 
1490 		if(obj_completed) {
1491 			break;
1492 		}
1493 
1494 #ifdef _MSC_VER
1495 		Sleep(1);
1496 #else
1497 		usleep(1000);
1498 #endif
1499 	}
1500 
1501 	printf("\n");
1502 
1503 	remove_wanted_object(s_id, tmp_toi);
1504 
1505 	/* Parse data from object to data buffer, return buffer length */
1506 
1507 	to = object_exist(tmp_toi, s, 1);
1508 
1509 	if(to->fec_enc_id == COM_NO_C_FEC_ENC_ID) {
1510 		buf = null_fec_decode_object(to, data_len, s);
1511 	}
1512 	else if(to->fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
1513 		buf = xor_fec_decode_object(to, data_len, s);
1514 	}
1515 	else if(to->fec_enc_id == RS_FEC_ENC_ID) {
1516 		buf = rs_fec_decode_object(to, data_len, s);
1517 	}
1518 	else if(to->fec_enc_id == SB_SYS_FEC_ENC_ID && to->fec_inst_id == REED_SOL_FEC_INST_ID) {
1519 		buf = rs_fec_decode_object(to, data_len, s);
1520 	}
1521 
1522 	if(buf == NULL) {
1523 		*retval = -1;
1524 	}
1525 	else {
1526 		*toi = tmp_toi;
1527 	}
1528 
1529 	free_object(to, s, 1);
1530 	return buf;
1531 }
1532 
1533 char* alc_recv3(int s_id, unsigned long long *toi, int *retval) {
1534 
1535 	BOOL obj_completed = FALSE;
1536 	alc_session_t *s;
1537 
1538 	unsigned long long tmp_toi = 0;
1539 
1540 	trans_obj_t *to;
1541 	char *tmp_filename = NULL;
1542 
1543 	s = get_alc_session(s_id);
1544 
1545 	while(1) {
1546 
1547 		to = s->obj_list;
1548 
1549 		if(s->state == SExiting) {
1550 			/*printf("alc_recv3() SExiting\n");
1551 			fflush(stdout);*/
1552 			*retval = -2;
1553 			return NULL;
1554 		}
1555 		else if(s->state == SClosed) {
1556 			/*printf("alc_recv3() SClosed\n");
1557 			fflush(stdout);*/
1558 			*retval = 0;
1559 			return NULL;
1560 		}
1561 		else if(((s->state == STxStopped) && (to == NULL))) {
1562 			/*printf("alc_recv3() STxStopped, to == NULL\n");
1563 			fflush(stdout);*/
1564 			*retval = -3;
1565 			return NULL;
1566 		}
1567 
1568 		while(to != NULL) {
1569 
1570 			obj_completed = FALSE;
1571 
1572 			if(s->state == SExiting) {
1573 				/*printf("alc_recv3() SExiting\n");
1574 				fflush(stdout);*/
1575 				*retval = -2;
1576 				return NULL;
1577 			}
1578 			else if(s->state == SClosed) {
1579 				/*printf("alc_recv3() SClosed\n");
1580 				fflush(stdout);*/
1581 				*retval = 0;
1582 				return NULL;
1583 			}
1584 			else if(s->state == STxStopped) {
1585 				break;
1586 			}
1587 
1588 			obj_completed = object_completed(to);
1589 
1590 			if(obj_completed) {
1591 				tmp_toi = to->toi;
1592 				break;
1593 			}
1594 
1595 			to = to->next;
1596 		}
1597 
1598 		if(obj_completed) {
1599 			break;
1600 		}
1601 		else if(s->state == STxStopped) {
1602 
1603 			/* Check if there is completed object after A-flag is received */
1604 
1605 			to = s->obj_list;
1606 
1607 			while(to != NULL) {
1608 
1609 				obj_completed = object_completed(to);
1610 
1611 				if(obj_completed) {
1612 					tmp_toi = to->toi;
1613 					break;
1614 				}
1615 
1616 				to = to->next;
1617 			}
1618 
1619 			if(obj_completed) {
1620 				break;
1621 			}
1622 			else {
1623 				/*printf("alc_recv3() STxStopped, any object not completed\n");
1624 				fflush(stdout);*/
1625 				*retval = -3;
1626 				return NULL;
1627 			}
1628 		}
1629 
1630 #ifdef _MSC_VER
1631 		Sleep(1);
1632 #else
1633 		usleep(1000);
1634 #endif
1635 	}
1636 
1637 	remove_wanted_object(s_id, tmp_toi);
1638 
1639 	if(!(tmp_filename = (char*)calloc((strlen(to->tmp_filename) + 1), sizeof(char)))) {
1640 		printf("Could not alloc memory for tmp_filename!\n");
1641 		*retval = -1;
1642 		return NULL;
1643 	}
1644 
1645 	memcpy(tmp_filename, to->tmp_filename, strlen(to->tmp_filename));
1646 
1647 	free_object(to, s, 1);
1648 	*toi = tmp_toi;
1649 
1650 	return tmp_filename;
1651 }
1652 
1653 char* fdt_recv(int s_id, unsigned long long *data_len, int *retval,
1654 			   unsigned char *content_enc_algo, int* fdt_instance_id) {
1655 
1656    alc_session_t *s;
1657    char *buf = NULL; /* Buffer where to construct the object from data units */
1658    trans_obj_t *to;
1659 
1660    s = get_alc_session(s_id);
1661 
1662    while(1) {
1663 	   to = s->fdt_list;
1664 
1665 	   if(s->state == SExiting) {
1666 		   /*printf("fdt_recv() SExiting\n");
1667 		   fflush(stdout);*/
1668 		   *retval = -2;
1669 		   return NULL;
1670 	   }
1671 	   else if(s->state == SClosed) {
1672 		   /*printf("fdt_recv() SClosed\n");
1673 		   fflush(stdout);*/
1674 		   *retval = 0;
1675 		   return NULL;
1676 	   }
1677 	   else if(s->state == STxStopped) {
1678 		   /*printf("fdt_recv() STxStopped\n");
1679 		   fflush(stdout);*/
1680 		   *retval = -3;
1681 		   return NULL;
1682 	   }
1683 
1684 	   if(to == NULL) {
1685 
1686 #ifdef _MSC_VER
1687 		   Sleep(1);
1688 #else
1689 		   usleep(1000);
1690 #endif
1691 		   continue;
1692 	   }
1693 
1694 	   do {
1695 		   if(object_completed(to)) {
1696 			   set_received_instance(s, (unsigned int)to->toi);
1697 
1698 			   *content_enc_algo = to->content_enc_algo;
1699 			   *fdt_instance_id = (int)to->toi;
1700 
1701 			   if(to->fec_enc_id == COM_NO_C_FEC_ENC_ID) {
1702 				   buf = null_fec_decode_object(to, data_len, s);
1703 			   }
1704 			   else if(to->fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
1705 				   buf = xor_fec_decode_object(to, data_len, s);
1706 			   }
1707 			   else if(to->fec_enc_id == RS_FEC_ENC_ID) {
1708 				   buf = rs_fec_decode_object(to, data_len, s);
1709 			   }
1710 			   else if(to->fec_enc_id == SB_SYS_FEC_ENC_ID && to->fec_inst_id == REED_SOL_FEC_INST_ID) {
1711 				   buf = rs_fec_decode_object(to, data_len, s);
1712 			   }
1713 
1714 			   if(buf == NULL) {
1715 				   *retval = -1;
1716 			   }
1717 
1718 			   free_object(to, s, 0);
1719 			   return buf;
1720 		   }
1721 		   to = to->next;
1722 	   } while(to != NULL);
1723 
1724 #ifdef _MSC_VER
1725 	   Sleep(1);
1726 #else
1727 	   usleep(1000);
1728 #endif
1729    }
1730 
1731    return buf;
1732 }
1733 
1734 trans_obj_t* object_exist(unsigned long long toi, alc_session_t *s, int type) {
1735 
1736   trans_obj_t *trans_obj = NULL;
1737 
1738   if(type == 0) {
1739 	  trans_obj = s->fdt_list;
1740   }
1741   else if(type == 1) {
1742 	  trans_obj = s->obj_list;
1743   }
1744 
1745   if(trans_obj != NULL) {
1746 	  for(;;) {
1747 		  if(trans_obj->toi == toi) {
1748 			  break;
1749 		  }
1750 		  if(trans_obj->next == NULL) {
1751 			  trans_obj = NULL;
1752 			  break;
1753 		  }
1754 		  trans_obj = trans_obj->next;
1755 	  }
1756   }
1757 
1758   return trans_obj;
1759 }
1760 
1761 BOOL object_completed(trans_obj_t *to) {
1762 
1763 	BOOL ready = FALSE;
1764 
1765 	if(to->nb_of_ready_blocks == to->bs->N) {
1766 		ready = TRUE;
1767 	}
1768 
1769 	return ready;
1770 }
1771 
1772 BOOL block_ready_to_decode(trans_block_t *tb) {
1773 
1774 	BOOL ready = FALSE;
1775 
1776 	if(tb->nb_of_rx_units >= tb->k) {
1777 		ready = TRUE;
1778 	}
1779 
1780 	return ready;
1781 }
1782