1 /** \file alc_tx.c \brief ALC level sending
2  *
3  *  $Author: peltotal $ $Date: 2007/02/28 08:58:00 $ $Revision: 1.114 $
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 <sys/types.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <assert.h>
40 #include <sys/timeb.h>
41 
42 #ifdef _MSC_VER
43 #include <process.h>
44 #else
45 #include <sys/socket.h>
46 #include <netdb.h>
47 #include <unistd.h>
48 #endif
49 
50 #include "alc_tx.h"
51 #include "alc_channel.h"
52 #include "alc_session.h"
53 #include "transport.h"
54 #include "lct_hdr.h"
55 #include "null_fec.h"
56 #include "xor_fec.h"
57 #include "rs_fec.h"
58 #include "alc_hdr.h"
59 #include "mad_rlc.h"
60 #include "fec.h"
61 
62 /**
63  * This is a private function which adds packet to transmission queue when TX_THREAD mode is used.
64  *
65  * @param s pointer to the session
66  * @param sendbuf pointer to data to be added to transmission queue
67  * @param sendlen lenght of data
68  *
69  * @return > 0 in success, 0 or -1 in error cases.
70  *
71  */
72 
add_pkt_to_tx_queue(alc_session_t * s,unsigned char * sendbuf,unsigned int sendlen)73 int add_pkt_to_tx_queue(alc_session_t *s, unsigned char *sendbuf,  unsigned int sendlen) {
74 	int retval = 0;
75 	tx_queue_t *pkt;
76 	int i;
77 	alc_channel_t *ch;
78 
79 	if(s->tx_queue_size == MAX_TX_QUEUE_SIZE) {
80 		return retval;
81 	}
82 
83 	/* Allocate memory for pkt */
84 	if(!(pkt = (tx_queue_t*)calloc(1, sizeof(tx_queue_t)))) {
85 		printf("Could not alloc memory for tx_queue pkt!\n");
86 		return -1;
87 	}
88 
89 	pkt->nb_tx_ch = 0;
90 	pkt->next = NULL;
91 	pkt->datalen = sendlen;
92 	pkt->data = sendbuf;
93 
94 	if(s->tx_queue_begin == NULL) {
95 
96 		s->tx_queue_begin = pkt;
97 		s->tx_queue_end = pkt;
98 
99 		for(i = 0; i < s->nb_channel; i++) {
100 			ch = s->ch_list[i];
101 			ch->ready = FALSE;
102 			ch->queue_ptr = s->tx_queue_begin;
103 
104 			if(s->cc_id == RLC) {
105 				if(ch->ch_id != 0) {
106 					ch->wait_after_sp = RLC_WAIT_AFTER_SP;
107 					ch->start_sending = FALSE;
108 				}
109 			}
110 		}
111 
112 		s->nb_ready_channel = 0;
113 
114 		if(s->cc_id == RLC) {
115 			s->nb_sending_channel = 1;
116 		}
117 	}
118 	else {
119 		s->tx_queue_end->next = pkt;
120 		s->tx_queue_end = pkt;
121 
122 		for(i = 0; i < s->nb_channel; i++) {
123 			ch = s->ch_list[i];
124 
125 			if(ch->queue_ptr == NULL) {
126 				ch->queue_ptr = s->tx_queue_end;
127 			}
128 		}
129 	}
130 
131 	s->tx_queue_size++;
132 
133 	return sendlen;
134 }
135 
136 /**
137  * This function a private function which sends one unit to channel or tx_queue.
138  *
139  * @param tr_unit pointer to transport unit to be sent
140  * @param tr_block pointer to transport block that this units belongs
141  * @param s pointer to session
142  * @param ch pointer to channel
143  * @param toi transport object identifier
144  * @param transfer_len length of transport object
145  * @param max_sb_len maximum source block length
146  * @param es_len encoding symbol length
147  * @param fec_enc_id FEC encoding id
148  * @param fec_inst_id FEC instance id
149  *
150  * @return 0 in success, -1 or -2  in error cases/stopping situations
151  *
152  */
153 
send_unit(trans_unit_t * tr_unit,trans_block_t * tr_block,alc_session_t * s,alc_channel_t * ch,unsigned long long toi,unsigned long long transfer_len,unsigned int max_sb_len,unsigned short es_len,unsigned char fec_enc_id,unsigned short fec_inst_id)154 int send_unit(trans_unit_t *tr_unit, trans_block_t *tr_block, alc_session_t *s,
155 	      alc_channel_t *ch, unsigned long long toi, unsigned long long transfer_len,
156 	      unsigned int max_sb_len, unsigned short es_len,
157 	      unsigned char fec_enc_id, unsigned short fec_inst_id) {
158 
159   int hdrlen;		/* length of total ALC header */
160 
161   unsigned char pkt[MAX_PACKET_LENGTH];
162   int sendlen = 0;
163   unsigned char *sendbuf;
164 
165   def_lct_hdr_t *def_lct_hdr;
166 
167   unsigned short half_word1;
168   unsigned short half_word2;
169   unsigned int word;
170 
171   unsigned short max_16bits = 0xFFFF;
172   unsigned int max_32bits = 0xFFFFFFFF;
173 
174   unsigned long long max_48bits = 0xFFFFFFFFFFFFULL;
175   unsigned long long  max_64bits = 0xFFFFFFFFFFFFFFFFULL;
176 
177   hdrlen = sizeof(def_lct_hdr_t);
178 
179   memset(pkt, 0, MAX_PACKET_LENGTH);
180   def_lct_hdr = (def_lct_hdr_t*)pkt;
181 
182   def_lct_hdr->version = ALC_VERSION;
183   def_lct_hdr->flag_c = 0;
184   def_lct_hdr->reserved = 0;
185   def_lct_hdr->flag_t = 0;
186   def_lct_hdr->flag_r = 0;
187 
188   def_lct_hdr->flag_a = 0;
189   def_lct_hdr->flag_b = 0; /* TODO */
190 
191   def_lct_hdr->codepoint = fec_enc_id;
192 
193   def_lct_hdr->cci = htonl(0);
194 
195   if(s->half_word) {
196 		if(((s->tsi <= max_16bits) && (toi <= max_16bits))) {
197 			def_lct_hdr->flag_s = 0;
198 			def_lct_hdr->flag_o = 0;
199 			def_lct_hdr->flag_h = 1;
200 
201 			half_word1 = (unsigned short)s->tsi;
202 			half_word2 = (unsigned short)toi;
203 
204 			word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
205 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
206 			hdrlen += 4;
207 		}
208 		else if(((((s->tsi <= max_16bits) && (((toi > max_16bits) && (toi <= max_32bits))))) ||
209 			 (((toi <= max_16bits) && (((s->tsi > max_16bits) && (s->tsi <= max_32bits))))))) {
210 			def_lct_hdr->flag_s = 1;
211 			def_lct_hdr->flag_o = 1;
212 			def_lct_hdr->flag_h = 0;
213 
214 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
215 			hdrlen += 4;
216 
217 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
218 			hdrlen += 4;
219 		}
220 		else if((((s->tsi > max_16bits) && (s->tsi <= max_32bits))) &&
221 			 (((toi > max_16bits) && (toi <= max_32bits)))) {
222 			def_lct_hdr->flag_s = 1;
223 			def_lct_hdr->flag_o = 1;
224 			def_lct_hdr->flag_h = 0;
225 
226 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
227 			hdrlen += 4;
228 
229 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
230 			hdrlen += 4;
231 		}
232 		else if(((s->tsi <= max_16bits) && (((toi > max_32bits) && (toi <= max_48bits))))) {
233 			def_lct_hdr->flag_s = 0;
234 			def_lct_hdr->flag_o = 1;
235 			def_lct_hdr->flag_h = 1;
236 
237 			half_word1 = (unsigned short)s->tsi;
238 			half_word2 = (unsigned short)((toi >> 32) & 0x0000FFFF);
239 			word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
240 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
241 			hdrlen += 4;
242 
243 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
244 			hdrlen += 4;
245 		}
246 		else if(((toi < max_16bits) && (((s->tsi > max_32bits) && (s->tsi <= max_48bits))))) {
247 
248 			def_lct_hdr->flag_s = 1;
249 			def_lct_hdr->flag_o = 0;
250 			def_lct_hdr->flag_h = 1;
251 
252 			word = (unsigned int)((s->tsi >> 16) & 0xFFFFFFFF);
253 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
254 			hdrlen += 4;
255 
256 			half_word1 = (unsigned short)(s->tsi & 0x0000FFFF);
257 			half_word2 = (unsigned short)toi;
258 
259 			word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
260 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
261 			hdrlen += 4;
262 		}
263 		else if((((s->tsi > max_32bits) && (s->tsi <= max_48bits))) &&
264 			 (((toi > max_32bits) && (toi <= max_48bits)))) {
265 			def_lct_hdr->flag_s = 1;
266 			def_lct_hdr->flag_o = 1;
267 			def_lct_hdr->flag_h = 1;
268 
269 			word = (unsigned int)((s->tsi >> 16) & 0xFFFFFFFF);
270 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
271 			hdrlen += 4;
272 
273 			half_word1 = (unsigned short)(s->tsi & 0x0000FFFF);
274 			half_word2 = (unsigned short)((toi >> 32) & 0x0000FFFF);
275 			word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
276 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
277 			hdrlen += 4;
278 
279 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
280 			hdrlen += 4;
281 		}
282 		else if((((s->tsi > max_16bits) && (s->tsi <= max_32bits))) &&
283 			 (((toi > max_32bits) && (toi <= max_64bits)))) {
284 			def_lct_hdr->flag_s = 1;
285 			def_lct_hdr->flag_o = 2;
286 			def_lct_hdr->flag_h = 0;
287 
288 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
289 			hdrlen += 4;
290 
291 			word = (unsigned int)((toi >> 32) & 0xFFFFFFFF);
292 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
293 			hdrlen += 4;
294 
295 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
296 			hdrlen += 4;
297 		}
298 		else if(((s->tsi < max_16bits) && ((toi > max_48bits) && (toi <= max_64bits)))) {
299 			def_lct_hdr->flag_s = 1;
300 			def_lct_hdr->flag_o = 2;
301 			def_lct_hdr->flag_h = 0;
302 
303 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
304 			hdrlen += 4;
305 
306 			word = (unsigned int)((toi >> 32) & 0xFFFFFFFF);
307 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
308 			hdrlen += 4;
309 
310 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
311 			hdrlen += 4;
312 		}
313 		else {
314 			printf("TSI & TOI field combination not supported!\n");
315 			fflush(stdout);
316 			return -1;
317 		}
318 	}
319 	else {
320 		def_lct_hdr->flag_s = 1;
321 		def_lct_hdr->flag_h = 0;
322 
323 		*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
324 		hdrlen += 4;
325 
326 		if(toi <= max_32bits) {
327 			def_lct_hdr->flag_o = 1;
328 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
329 			hdrlen += 4;
330 		}
331 		else if(((toi > max_32bits) && (toi <= max_64bits))) {
332 			def_lct_hdr->flag_o = 2;
333 
334 			word = (unsigned int)((toi >> 32) & 0xFFFFFFFF);
335 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
336 			hdrlen += 4;
337 
338 			*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
339 			hdrlen += 4;
340 		}
341 		else {
342 			printf("TSI & TOI field combination not supported!\n");
343 			fflush(stdout);
344 			return -1;
345 		}
346 	}
347 
348 	if(toi == FDT_TOI) {
349 	  hdrlen += add_fdt_lct_he(def_lct_hdr, hdrlen, s->fdt_instance_id);
350 
351 #ifdef USE_ZLIB
352 	  if(s->encode_content == ZLIB_FDT || s->encode_content == ZLIB_FDT_AND_GZIP_FILES ) {
353 	    hdrlen += add_cenc_lct_he(def_lct_hdr, hdrlen, (unsigned char)ZLIB);
354 	  }
355 #endif
356 
357 	}
358 
359 	if(((toi == FDT_TOI) || (s->use_fec_oti_ext_hdr == 1))) {
360 
361 	  if(fec_enc_id == COM_NO_C_FEC_ENC_ID) {
362 
363 	    hdrlen += add_fti_0_2_128_130_lct_he(def_lct_hdr, hdrlen, transfer_len, 0,
364 						 es_len, max_sb_len);
365 	  }
366 	  else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
367 
368 	    hdrlen += add_fti_0_2_128_130_lct_he(def_lct_hdr, hdrlen, transfer_len, 0,
369 						 es_len, max_sb_len);
370 	  }
371 	  else if(fec_enc_id == RS_FEC_ENC_ID) {
372 
373 	    hdrlen += add_fti_3_lct_he(def_lct_hdr, hdrlen, transfer_len, (unsigned char)GF_BITS,
374 				       (unsigned char)1, es_len,
375 				       (unsigned short)tr_block->max_k, (unsigned short)tr_block->max_n);
376 	  }
377 	  else if((fec_enc_id == COM_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID)) {
378 
379 	    hdrlen += add_fti_0_2_128_130_lct_he(def_lct_hdr, hdrlen, transfer_len, fec_inst_id,
380 						 es_len, max_sb_len);
381 	  }
382 
383 	  else if(fec_enc_id == SB_SYS_FEC_ENC_ID) {
384 
385 	    hdrlen += add_fti_129_lct_he(def_lct_hdr, hdrlen, transfer_len, fec_inst_id,
386 					 es_len, (unsigned short)tr_block->max_k, (unsigned short)tr_block->max_n);
387 	  }
388 	}
389 
390 	/* TODO: add other LCT header extensions here */
391 	/*if(nop) {
392 	  hdrlen += add_nop_lct_he();
393 	  }
394 	  if(auth) {
395 	  hdrlen += add_auth_lct_he();
396 	  }
397 	  if(time) {
398 	  hdrlen += add_time_lct_he();
399 	  }
400 	*/
401 
402 	def_lct_hdr->hdr_len = hdrlen >> 2; /* Header length in 32-bit words */
403 	*(unsigned short*)def_lct_hdr = htons(*(unsigned short*)def_lct_hdr);
404 
405 	/* FEC Payload ID */
406 
407 	if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))) {
408 
409 	  hdrlen += add_alc_fpi_0_130(def_lct_hdr, hdrlen, (unsigned short)tr_block->sbn,
410 				      (unsigned short)tr_unit->esi);
411 	}
412 	else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
413 
414 	  hdrlen += add_alc_fpi_2_128(def_lct_hdr, hdrlen, tr_block->sbn, tr_unit->esi);
415 	}
416 	else if(fec_enc_id == RS_FEC_ENC_ID) {
417 
418 	  hdrlen += add_alc_fpi_3(def_lct_hdr, hdrlen, tr_block->sbn,
419 				  tr_unit->esi, GF_BITS);
420 	}
421 	else if(fec_enc_id == SB_LB_E_FEC_ENC_ID) {
422 
423 	  hdrlen += add_alc_fpi_2_128(def_lct_hdr, hdrlen, tr_block->sbn, tr_unit->esi);
424 	}
425 	else if(fec_enc_id == SB_SYS_FEC_ENC_ID) {
426 
427 	  hdrlen += add_alc_fpi_129(def_lct_hdr, hdrlen, tr_block->sbn,
428 				    (unsigned short)tr_block->k,
429 				    (unsigned short)tr_unit->esi);
430 	}
431 
432 	memcpy(pkt + hdrlen, tr_unit->data, tr_unit->len);
433 	sendlen = hdrlen + tr_unit->len;
434 
435 	if(ch != NULL) {
436 
437 		if (ch->s->calculate_session_size == FALSE) {
438 
439 			/*if(toi == 0 && tr_block->sbn == 0 && tr_unit->esi == 0) {
440 			}
441 			else {*/
442 		  sendto(ch->tx_sock, (char *)pkt, sendlen, 0,
443 		    ch->addrinfo->ai_addr, ch->addrinfo->ai_addrlen);
444 			/*}*/
445 		}
446 
447 		add_session_sent_bytes(s->s_id, sendlen);
448 
449 		/* Should we take UDP/IP headers into account? */
450 		/* UDP */
451 		add_session_sent_bytes(s->s_id, 8);
452 		/* IPv4 or IPv6 */
453 		if(s->addr_family == PF_INET) {
454 		  add_session_sent_bytes(s->s_id, 20);
455 		}
456 		else {
457 		  add_session_sent_bytes(s->s_id, 40);
458 		}
459 	}
460 	else {
461 		if(!(sendbuf = (unsigned char*)calloc((sendlen + 1), sizeof(unsigned char)))) {
462 			printf("Could not alloc memory for tx queue packet!\n");
463 			fflush(stdout);
464 			return -1;
465 		}
466 
467 		memcpy(sendbuf, pkt, sendlen);
468 
469 		while(1) {
470 
471 			if(s->state == SExiting) {
472 				return -2;
473 			}
474 
475 			if(add_pkt_to_tx_queue(s, sendbuf, sendlen) > 0) {
476 				break;
477 			}
478 			else {
479 #ifdef _MSC_VER
480 				Sleep(10);
481 #else
482 				usleep(10000);
483 #endif
484 			}
485 		}
486 	}
487 
488 	return sendlen;
489 }
490 
491 /**
492  * This is a private function which calculates packet length used in session.
493  *
494  * @param s pointer to the session
495  *
496  * @return packet length for the session
497  *
498  */
499 
calculate_packet_length(alc_session_t * s)500 int calculate_packet_length(alc_session_t *s) {
501 
502 	int packet_length = 0;
503 
504 	if(s->addr_family == PF_INET) {
505 
506 		if(s->use_fec_oti_ext_hdr == 1) {
507 
508 			/* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */
509 
510 			if(((s->def_fec_enc_id == COM_NO_C_FEC_ENC_ID) ||
511 				(s->def_fec_enc_id == COM_FEC_ENC_ID) ||
512 				(s->def_fec_enc_id == RS_FEC_ENC_ID))) {
513 				packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 20);
514 			}
515 			else if(((s->def_fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) ||
516 				 (s->def_fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
517 				 (s->def_fec_enc_id == SB_SYS_FEC_ENC_ID))) {
518 				packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 20);
519 			}
520 		}
521 		else if(s->use_fec_oti_ext_hdr == 0) {
522 			/* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */
523 
524 			if(((s->def_fec_enc_id == COM_NO_C_FEC_ENC_ID) ||
525 				(s->def_fec_enc_id == COM_FEC_ENC_ID) ||
526 				(s->def_fec_enc_id == RS_FEC_ENC_ID))) {
527 				packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 20);
528 			}
529 			else if(((s->def_fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) ||
530 				 (s->def_fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
531 				 (s->def_fec_enc_id == SB_SYS_FEC_ENC_ID))) {
532 				packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 20);
533 			}
534 		}
535 	}
536 	else if(s->addr_family == PF_INET6) {
537 		if(s->use_fec_oti_ext_hdr == 1) {
538 			/* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */
539 
540 			if(((s->def_fec_enc_id == COM_NO_C_FEC_ENC_ID) ||
541 				(s->def_fec_enc_id == COM_FEC_ENC_ID) ||
542 				(s->def_fec_enc_id == RS_FEC_ENC_ID))) {
543 				packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 40);
544 			}
545 			else if(((s->def_fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) ||
546 				 (s->def_fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
547 				 (s->def_fec_enc_id == SB_SYS_FEC_ENC_ID))) {
548 				packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 40);
549 			}
550 		}
551 		else if(s->use_fec_oti_ext_hdr == 0) {
552 			/* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */
553 
554 			if(((s->def_fec_enc_id == COM_NO_C_FEC_ENC_ID) ||
555 				(s->def_fec_enc_id == COM_FEC_ENC_ID) ||
556 				(s->def_fec_enc_id == RS_FEC_ENC_ID))) {
557 				packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 20);
558 			}
559 			else if(((s->def_fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) ||
560 				 (s->def_fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
561 				 (s->def_fec_enc_id == SB_SYS_FEC_ENC_ID))) {
562 				packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 20);
563 			}
564 		}
565 	}
566 
567 	return packet_length;
568 }
569 
570 /**
571  * This is a private function which calculates actual bitrate for the session.
572  *
573  * @param s pointer to the session
574  *
575  * @return actual bitrate for the session
576  *
577  */
578 
session_kbit_rate(const alc_session_t * s)579 float session_kbit_rate(const alc_session_t *s) {
580 
581     double curr_time;
582     float actual_kbit_rate = (float)s->def_tx_rate;
583     struct timeb timeb_current_time;
584 
585     ftime(&timeb_current_time);
586 
587     curr_time = timeb_current_time.time+timeb_current_time.millitm/1000.0;
588 
589     if(s->sent_bytes > 0 && curr_time > s->ftimestarttime) {
590         actual_kbit_rate = (float)((s->sent_bytes*8/1024.0) / (curr_time - s->ftimestarttime));
591     }
592 
593     /*printf("\n%f", curr_time-s->ftimestarttime);
594     printf(" %f", actual_kbit_rate);*/
595     return actual_kbit_rate;
596 }
597 
alc_send(int s_id,int tx_mode,char * buf,int buf_len,unsigned long long toi,unsigned long long transfer_len,unsigned short es_len,unsigned int max_sb_len,unsigned int sbn,unsigned char fec_enc_id,unsigned short fec_inst_id)598 int alc_send(int s_id, int tx_mode, char *buf, int buf_len,
599 			 unsigned long long toi, unsigned long long transfer_len,
600 			 unsigned short es_len, unsigned int max_sb_len, unsigned int sbn,
601 			 unsigned char fec_enc_id, unsigned short fec_inst_id) {
602 
603 	trans_block_t *tr_block = NULL;
604 	trans_unit_t *tr_unit = NULL;
605 	unsigned int i = 0;
606 
607 	alc_channel_t *ch = NULL;
608 	alc_session_t *s = NULL;
609 
610 	int sent = 0;
611 	int tb_data_left = 0;
612 
613 	int packet_length = 0;
614 	int addr_family = 0;
615 	int use_fec_oti_ext_hdr = 0;
616 	double loss_prob = 0;
617 	int retval = 0;
618 	double tx_percent = 0;
619 
620 
621     double packetpersec = 0;
622     double interval = 0;
623     double block_interval = 0;
624     long sleep_interval = 0;
625     float diff_kbit_rate = 0;
626     double relative_error = 0;
627     double correction = 0;
628 
629 	s = get_alc_session(s_id);
630 
631 	if(tx_mode != TX_THREAD) { /* We have only the base channel in this case */
632 		ch = s->ch_list[0]; /* Let's take the base channel */
633 		addr_family = s->addr_family;
634 		use_fec_oti_ext_hdr = s->use_fec_oti_ext_hdr;
635 
636 		if(toi == FDT_TOI) {
637 
638 			/* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FDT + EXT_CENC + EXT_FTI + FEC_PL_ID + UDP + IP */
639 
640 			if(addr_family == PF_INET) {
641 
642 				if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
643 					|| (fec_enc_id == RS_FEC_ENC_ID))) {
644 						packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 4 + 8 + 20);
645 				}
646 				else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
647 					(fec_enc_id == SB_SYS_FEC_ENC_ID))) {
648 						packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 8 + 8 + 20);
649 				}
650 			}
651 			else if(addr_family == PF_INET6) {
652 
653 				if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
654 					|| (fec_enc_id == RS_FEC_ENC_ID))) {
655 						packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 4 + 8 + 40);
656 				}
657 				else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
658 					(fec_enc_id == SB_SYS_FEC_ENC_ID))) {
659 						packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 8 + 8 + 40);
660 				}
661 			}
662 		}
663 		else {
664 			if(addr_family == PF_INET) {
665 
666 				if(use_fec_oti_ext_hdr == 1) {
667 					/* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */
668 
669 					if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
670 						|| (fec_enc_id == RS_FEC_ENC_ID))) {
671 							packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 20);
672 					}
673 					else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
674 						(fec_enc_id == SB_SYS_FEC_ENC_ID))) {
675 							packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 20);
676 					}
677 				}
678 				else if(use_fec_oti_ext_hdr == 0) {
679 
680 					/* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */
681 
682 					if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
683 						|| (fec_enc_id == RS_FEC_ENC_ID))) {
684 							packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 20);
685 					}
686 					else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
687 						(fec_enc_id == SB_SYS_FEC_ENC_ID))) {
688 							packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 20);
689 					}
690 				}
691 			}
692 			else if(addr_family == PF_INET6) {
693 
694 				if(use_fec_oti_ext_hdr == 1) {
695 					/* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */
696 
697 					if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
698 						|| (fec_enc_id == RS_FEC_ENC_ID))) {
699 							packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 40);
700 					}
701 					else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
702 						(fec_enc_id == SB_SYS_FEC_ENC_ID))) {
703 							packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 40);
704 					}
705 				}
706 				else if(use_fec_oti_ext_hdr == 0) {
707 
708 					/* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */
709 
710 					if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
711 						|| (fec_enc_id == RS_FEC_ENC_ID))) {
712 							packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 40);
713 					}
714 					else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
715 						(fec_enc_id == SB_SYS_FEC_ENC_ID))) {
716 							packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 40);
717 					}
718 				}
719 			}
720 		}
721 	}
722 
723 	if(fec_enc_id == COM_NO_C_FEC_ENC_ID) {
724 		tr_block = null_fec_encode_src_block(buf, buf_len, sbn, es_len);
725 	}
726 	else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
727 		tr_block = xor_fec_encode_src_block(buf, buf_len, sbn, es_len);
728 	}
729 	else if(fec_enc_id == RS_FEC_ENC_ID) {
730 		tr_block = rs_fec_encode_src_block(buf, buf_len, sbn, es_len, s->def_fec_ratio,
731 			max_sb_len);
732 	}
733 	else if(((fec_enc_id == SB_SYS_FEC_ENC_ID) && (fec_inst_id == REED_SOL_FEC_INST_ID))) {
734 		tr_block = rs_fec_encode_src_block(buf, buf_len, sbn, es_len, s->def_fec_ratio,
735 			max_sb_len);
736 	}
737 	else {
738 		if(fec_enc_id < 128) {
739 			printf("FEC Encoding %i is not supported!\n", fec_enc_id);
740 		}
741 		else {
742 			printf("FEC Encoding %i/%i is not supported!\n", fec_enc_id, fec_inst_id);
743 		}
744 
745 		return -1;
746 	}
747 
748 	if(tr_block == NULL) {
749 		return -1;
750 	}
751 
752 	if(tx_mode != TX_THREAD) {
753 
754 		tb_data_left = es_len * tr_block->n;
755 		tr_unit = tr_block->unit_list;
756 
757 		for(i = 0; i < tr_block->n; i++) {
758 
759 			if(s->state == SPaused) {
760 				while(1) {
761 					if(s->state == SExiting) {
762 						return -2;
763 					}
764 
765 					if(s->state == SActive) {
766 						break;
767 					}
768 #ifdef _MSC_VER
769 					Sleep(1000);
770 #else
771 					usleep(1000000);
772 #endif
773 				}
774 			}
775 
776 			if(s->state == SExiting) {
777 				while(1) {
778 					free(tr_unit->data);
779 
780 					if(tr_unit->esi == (tr_block->n - 1)) {
781 						break;
782 					}
783 					tr_unit++;
784 				}
785 
786 				free(tr_block->unit_list);
787 				free(tr_block);
788 
789 				return -2;
790 			}
791 
792 			if (ch->s->calculate_session_size == FALSE) {
793 				packetpersec =
794 					((double)(ch->tx_rate * 1000) / (double)(packet_length * 8));
795 				interval = ((double)1 / packetpersec);
796 				block_interval = /*tr_block->n*/ 1*interval;
797 				sleep_interval = (long)(block_interval*1000);
798 				diff_kbit_rate = session_kbit_rate(ch->s)-ch->s->def_tx_rate;
799 				relative_error = (double)diff_kbit_rate/(double)ch->s->def_tx_rate;
800 				correction = 1;
801 
802 				//printf("\n%f ", relative_error);
803 				if(relative_error > 0.001) {
804 					correction = 1.0 + (relative_error*50.0);
805 				}
806 				else if(relative_error < -0.001) {
807 					relative_error = -relative_error;
808 					correction = 1.0 - (relative_error*50.0);
809 				}
810 
811 				//printf("%f ", correction);
812 				//printf("%d ", sleep_interval);
813 
814 				// Adjust the sleep interval according the diff_bit_rate value.
815 				sleep_interval = sleep_interval*correction;
816 				//printf("%d", sleep_interval);
817 
818 				if(sleep_interval > 0) {
819 #ifdef _MSC_VER
820 					Sleep(sleep_interval);
821 #else
822 					usleep(sleep_interval*1000);
823 #endif
824 				}
825 			}
826 
827 			loss_prob = 0;
828 
829 			if(s->simul_losses) {
830 				if(ch->previous_lost == TRUE) {
831 					loss_prob = s->loss_ratio2;
832 				}
833 				else {
834 					loss_prob = s->loss_ratio1;
835 				}
836 			}
837 
838 			if(!randomloss(loss_prob)) {
839 
840 				retval = send_unit(tr_unit, tr_block, s, ch, toi, transfer_len, max_sb_len, es_len,
841 					fec_enc_id, fec_inst_id);
842 
843 				if(retval < 0) {
844 
845 					while(1) {
846 
847 						free(tr_unit->data);
848 
849 						if(tr_unit->esi == (tr_block->n - 1)) {
850 							break;
851 						}
852 
853 						tr_unit++;
854 					}
855 
856 					free(tr_block->unit_list);
857 					free(tr_block);
858 
859 					return -1;
860 				}
861 
862 				sent += tr_unit->len;
863 
864 				add_object_sent_bytes(s_id, tb_data_left < tr_unit->len ?
865 					(unsigned int)tb_data_left : tr_unit->len);
866 
867 				tb_data_left -= tb_data_left < tr_unit->len ? tb_data_left : tr_unit->len;
868 
869 				if(((toi == FDT_TOI && s->verbosity == 4) || (toi != FDT_TOI && s->verbosity > 1))) {
870 
871 					tx_percent = (double)((double)(100 *
872 						((double)(long long)get_object_sent_bytes(s_id)/
873 						(double)(long long)transfer_len)));
874 
875 					if(((tx_percent >= (get_object_last_print_tx_percent(s_id) + 1))
876 						|| (tx_percent == 100))) {
877 							set_object_last_print_tx_percent(s_id, tx_percent);
878 							printf("%.2f%% of object sent (TOI=%llu)\n", tx_percent, toi);
879 					}
880 
881 					fflush(stdout);
882 				}
883 
884 				ch->previous_lost = FALSE;
885 			}
886 			else {
887 				ch->previous_lost = TRUE;
888 			}
889 
890 
891 			free(tr_unit->data);
892 			tr_unit++;
893 		}
894 
895 		free(tr_block->unit_list);
896 		free(tr_block);
897 	}
898 	else {
899 		tr_unit = tr_block->unit_list;
900 
901 		for(i = 0; i < tr_block->n; i++) {
902 
903 			retval = send_unit(tr_unit, tr_block, s, NULL, toi, transfer_len,
904 				max_sb_len, es_len, fec_enc_id, fec_inst_id);
905 
906 			if(retval == -1) {
907 				i--;
908 				continue;
909 			}
910 			else if(retval == -2) {
911 
912 				while(1) {
913 
914 					free(tr_unit->data);
915 
916 					if(tr_unit->esi == (tr_block->n - 1)) {
917 						break;
918 					}
919 
920 					tr_unit++;
921 				}
922 
923 				free(tr_block->unit_list);
924 				free(tr_block);
925 
926 				return retval;
927 			}
928 
929 			free(tr_unit->data);
930 			tr_unit++;
931 		}
932 
933 		free(tr_block->unit_list);
934 		free(tr_block);
935 	}
936 
937 	return sent;
938 }
939 
send_session_close_packet(int s_id)940 int send_session_close_packet(int s_id) {
941 
942 	int	sendlen;			     /* number of bytes to send */
943 	int	hdrlen;					/* length of total ALC header */
944 	int retval = 0;
945 
946 	alc_channel_t *ch;
947 
948 	unsigned char sendbuf[MAX_PACKET_LENGTH];	/* TU (hdrs+data) cannot be larger */
949 
950 	def_lct_hdr_t *def_lct_hdr;
951 
952 	unsigned short half_word1;
953 	unsigned short half_word2;
954 	unsigned int word;
955 
956 	assert(get_alc_session(s_id)!=NULL);
957 	ch = get_alc_session(s_id)->ch_list[0]; /* We send the close packet only to the base channel */
958 
959 	memset(sendbuf, 0, MAX_PACKET_LENGTH);
960 	def_lct_hdr = (def_lct_hdr_t*)sendbuf;
961 
962 	def_lct_hdr->version = ALC_VERSION;
963 	def_lct_hdr->flag_c = 0;
964 	def_lct_hdr->reserved = 0;
965 
966 	def_lct_hdr->flag_t = 0;
967 	def_lct_hdr->flag_r = 0;
968 	def_lct_hdr->flag_a = 1;
969 	def_lct_hdr->flag_b = 0;
970 	def_lct_hdr->codepoint = ch->s->def_fec_enc_id;
971 
972 	def_lct_hdr->cci = htonl(0);
973 
974 	hdrlen = sizeof(def_lct_hdr_t);
975 
976 	if(ch->s->tsi <= 0xFFFFFFFF) {
977 
978 		def_lct_hdr->flag_s = 1;
979 		def_lct_hdr->flag_o = 0;
980 		def_lct_hdr->flag_h = 0;
981 
982 		*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)ch->s->tsi);
983 		hdrlen += 4;
984 	}
985 	else {
986 		/* TSI field length 48 bits not possible without TOI field */
987 
988 		def_lct_hdr->flag_s = 1;
989 		def_lct_hdr->flag_o = 0;
990 		def_lct_hdr->flag_h = 1;
991 
992 		word = (unsigned int)((ch->s->tsi >> 16) & 0xFFFFFFFF);
993 		*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
994 		hdrlen += 4;
995 
996 		half_word1 = (unsigned short)(ch->s->tsi & 0x0000FFFF);
997 		half_word2 = (unsigned short)0;
998 
999 		word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
1000 		*(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
1001 		hdrlen += 4;
1002 	}
1003 
1004 	def_lct_hdr->hdr_len = hdrlen >> 2; /* Header length in 32-bit words */
1005 	*(unsigned short*)def_lct_hdr = htons(*(unsigned short*)def_lct_hdr);
1006 
1007 	sendlen = hdrlen;
1008 
1009 	if(ch->s->cc_id == RLC) {
1010 		retval = mad_rlc_fill_header(ch->s, (rlc_hdr_t*)(sendbuf + 4), ch->ch_id);
1011 	}
1012 
1013 	retval = sendto(ch->tx_sock, (char *)sendbuf, sendlen, 0,
1014 		ch->addrinfo->ai_addr, ch->addrinfo->ai_addrlen);
1015 
1016 	add_session_sent_bytes(s_id, sendlen);
1017 
1018         /* Should we take UDP/IP headers into account? */
1019         /* UDP */
1020         add_session_sent_bytes(s_id, 8);
1021         /* IPv4 or IPv6 */
1022         if(ch->s->addr_family == PF_INET) {
1023           add_session_sent_bytes(s_id, 20);
1024         }
1025         else {
1026           add_session_sent_bytes(s_id, 40);
1027         }
1028 
1029 	return retval;
1030 }
1031 
tx_thread(void * s)1032 void* tx_thread(void *s) {
1033 
1034   alc_session_t *session;
1035   alc_channel_t *channel;
1036   tx_queue_t *tmp_ptr;
1037 
1038   tx_queue_t *next_pkt;
1039   tx_queue_t *pkt;
1040 
1041   int i, j;
1042   int retcode;
1043   int packet_length;
1044 
1045   double interval;
1046   double packetpersec;
1047   double currenttime;
1048   double lasttime;
1049 
1050   double loss_prob;
1051 
1052   session = (alc_session_t *)s;
1053 
1054   packet_length = calculate_packet_length(session);
1055 
1056   packetpersec = ((double)(session->def_tx_rate * 1000) / (double)(packet_length * 8));
1057   interval = ((double)1 / packetpersec);
1058 
1059   /* interval is too small for FDT Instance, because in packet length calculation FDT Instance's
1060      extra header fields are not counted */
1061 
1062   while(session->state == SActive) {
1063 
1064     if(session->tx_queue_begin == NULL) {
1065 #ifdef _MSC_VER
1066       Sleep(1);
1067 #else
1068       usleep(1000);
1069 #endif
1070       continue;
1071     }
1072     else {
1073       break;
1074     }
1075   }
1076 
1077   lasttime = sec();
1078 
1079   while(session->state == SActive) {
1080 
1081     currenttime = sec();
1082 
1083 	if(session->calculate_session_size == FALSE) {
1084 
1085 		while(currenttime < (lasttime + interval)) {
1086 
1087 			if(session->optimize_tx_rate) {
1088 #ifdef _MSC_VER
1089 				Sleep(0);
1090 #else
1091 				usleep(0);
1092 #endif
1093 			}
1094 			else {
1095 #ifdef _MSC_VER
1096 				Sleep(1);
1097 #else
1098 				usleep(1000);
1099 #endif
1100 			}
1101 			currenttime = sec();
1102 		}
1103 	}
1104     for(i = 0; i < session->nb_channel; i++) {
1105 
1106       channel = session->ch_list[i];
1107 
1108       if(session->cc_id == RLC) {
1109 
1110 	if(channel->start_sending == FALSE) {
1111 	  continue;
1112 	}
1113 
1114 	if(channel->wait_after_sp > 0) {
1115 	  channel->wait_after_sp--;
1116 	  continue;
1117 	}
1118       }
1119 
1120       for(j = 0; j < channel->nb_tx_units; j++) {
1121 
1122 	if(channel->queue_ptr == NULL) {
1123 
1124 	  if(channel->ready == FALSE) {
1125 	    session->nb_ready_channel++;
1126 	    channel->ready = TRUE;
1127 	  }
1128 
1129 	  if(session->nb_ready_channel == session->nb_sending_channel) {
1130 
1131 	    pkt = session->tx_queue_begin;
1132 
1133 	    while(pkt != NULL) {
1134 	      next_pkt = pkt->next;
1135 	      free(pkt->data);
1136 	      free(pkt);
1137 	      pkt = next_pkt;
1138 	    }
1139 
1140 	    session->tx_queue_begin = NULL;
1141 	    session->tx_queue_size = 0;
1142 	  }
1143 
1144 	  break;
1145 	}
1146 
1147 	if(session->first_unit_in_loop) {
1148 
1149 	  if(session->cc_id == RLC) {
1150 	    mad_rlc_reset_tx_sp(session);
1151 	  }
1152 
1153 	  session->first_unit_in_loop = FALSE;
1154 	}
1155 	if(session->cc_id == RLC) {
1156 
1157 	  retcode = mad_rlc_fill_header(session, (rlc_hdr_t*)(channel->queue_ptr->data + 4),
1158 					channel->ch_id);
1159 
1160 	  if(retcode < 0) {
1161 	  }
1162 	}
1163 
1164 	loss_prob = 0;
1165 
1166 	if(session->simul_losses) {
1167 	  if(channel->previous_lost == TRUE) {
1168 	    loss_prob = channel->s->loss_ratio2; /*P_LOSS_WHEN_LOSS;*/
1169 	  }
1170 	  else {
1171 	    loss_prob = channel->s->loss_ratio1; /*P_LOSS_WHEN_OK;*/
1172 	  }
1173 	}
1174 
1175 	if(!randomloss(loss_prob)) {
1176 
1177 	  if(session->calculate_session_size == FALSE) {
1178 	    retcode = sendto(channel->tx_sock, (char*)channel->queue_ptr->data,
1179 			     channel->queue_ptr->datalen, 0, channel->addrinfo->ai_addr,
1180 			     channel->addrinfo->ai_addrlen);
1181 
1182 	    if(retcode < 0) {
1183 
1184 #ifdef _MSC_VER
1185 	      printf("sendto failed with: %d\n", WSAGetLastError());
1186 #else
1187 	      printf("sendto failed with: %d\n", errno);
1188 #endif
1189 	      break;
1190 	    }
1191 	  }
1192 
1193 	  add_session_sent_bytes(session->s_id, channel->queue_ptr->datalen);
1194 	  /* Should we take UDP/IP headers into account? */
1195 	  /* UDP */
1196 	  add_session_sent_bytes(session->s_id, 8);
1197 	  /* IPv4 or IPv6 */
1198 	  if(session->addr_family == PF_INET) {
1199 	    add_session_sent_bytes(session->s_id, 20);
1200 	  }
1201 	  else {
1202 	    add_session_sent_bytes(session->s_id, 40);
1203 	  }
1204 
1205 	  channel->previous_lost = FALSE;
1206 	}
1207 	else {
1208 	  channel->previous_lost = TRUE;
1209 	}
1210 
1211 	channel->queue_ptr->nb_tx_ch++;
1212 
1213 	if(channel->queue_ptr->nb_tx_ch == (unsigned int)session->nb_channel) {
1214 
1215 	  tmp_ptr = channel->queue_ptr->next;
1216 	  free(channel->queue_ptr->data);
1217 	  free(channel->queue_ptr);
1218 
1219 	  channel->queue_ptr = tmp_ptr;
1220 	  session->tx_queue_begin = tmp_ptr;
1221 	  session->tx_queue_size--;
1222 	}
1223 	else {
1224 	  channel->queue_ptr = channel->queue_ptr->next;
1225 	}
1226       }
1227     }
1228 
1229     lasttime += interval;
1230   }
1231 
1232 #ifdef _MSC_VER
1233   _endthread();
1234 #else
1235   pthread_exit(0);
1236 #endif
1237 
1238   return NULL;
1239 }
1240