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