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