alc_tx.c

Go to the documentation of this file.
00001 
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <sys/types.h>
00037 #include <string.h>
00038 #include <errno.h>
00039 #include <assert.h>
00040 #include <sys/timeb.h>
00041 
00042 #ifdef _MSC_VER
00043 #include <process.h>
00044 #else
00045 #include <sys/socket.h>
00046 #include <netdb.h>
00047 #include <unistd.h>
00048 #endif
00049 
00050 #include "alc_tx.h"
00051 #include "alc_channel.h"
00052 #include "alc_session.h"
00053 #include "transport.h"
00054 #include "lct_hdr.h"
00055 #include "null_fec.h"
00056 #include "xor_fec.h"
00057 #include "rs_fec.h"
00058 #include "alc_hdr.h"
00059 #include "mad_rlc.h"
00060 #include "fec.h"
00061 
00073 int add_pkt_to_tx_queue(alc_session_t *s, unsigned char *sendbuf,  unsigned int sendlen) {
00074         int retval = 0;
00075         tx_queue_t *pkt;
00076         int i;
00077         alc_channel_t *ch;
00078 
00079         if(s->tx_queue_size == MAX_TX_QUEUE_SIZE) {
00080                 return retval;
00081         }
00082 
00083         /* Allocate memory for pkt */
00084         if(!(pkt = (tx_queue_t*)calloc(1, sizeof(tx_queue_t)))) {
00085                 printf("Could not alloc memory for tx_queue pkt!\n");
00086                 return -1;
00087         }
00088 
00089         pkt->nb_tx_ch = 0;
00090         pkt->next = NULL;
00091         pkt->datalen = sendlen;
00092         pkt->data = sendbuf;
00093 
00094         if(s->tx_queue_begin == NULL) {
00095 
00096                 s->tx_queue_begin = pkt;
00097                 s->tx_queue_end = pkt;
00098 
00099                 for(i = 0; i < s->nb_channel; i++) {
00100                         ch = s->ch_list[i];
00101                         ch->ready = FALSE;
00102                         ch->queue_ptr = s->tx_queue_begin;
00103 
00104                         if(s->cc_id == RLC) {
00105                                 if(ch->ch_id != 0) {
00106                                         ch->wait_after_sp = RLC_WAIT_AFTER_SP;  
00107                                         ch->start_sending = FALSE;
00108                                 }
00109                         }
00110                 }
00111 
00112                 s->nb_ready_channel = 0;
00113 
00114                 if(s->cc_id == RLC) {
00115                         s->nb_sending_channel = 1;
00116                 }
00117         }
00118         else {
00119                 s->tx_queue_end->next = pkt;
00120                 s->tx_queue_end = pkt;
00121 
00122                 for(i = 0; i < s->nb_channel; i++) {
00123                         ch = s->ch_list[i];
00124                         
00125                         if(ch->queue_ptr == NULL) {
00126                                 ch->queue_ptr = s->tx_queue_end;
00127                         }
00128                 }
00129         }
00130 
00131         s->tx_queue_size++;
00132 
00133         return sendlen;
00134 }
00135 
00154 int send_unit(trans_unit_t *tr_unit, trans_block_t *tr_block, alc_session_t *s,
00155               alc_channel_t *ch, unsigned long long toi, unsigned long long transfer_len,
00156               unsigned int max_sb_len, unsigned short es_len,
00157               unsigned char fec_enc_id, unsigned short fec_inst_id) {
00158 
00159   int hdrlen;           /* length of total ALC header */
00160   
00161   unsigned char pkt[MAX_PACKET_LENGTH];
00162   int sendlen = 0;
00163   unsigned char *sendbuf;
00164   
00165   def_lct_hdr_t *def_lct_hdr;
00166   
00167   unsigned short half_word1;
00168   unsigned short half_word2;
00169   unsigned int word;
00170   
00171   unsigned short max_16bits = 0xFFFF;
00172   unsigned int max_32bits = 0xFFFFFFFF;
00173   
00174   unsigned long long max_48bits = 0xFFFFFFFFFFFFULL;
00175   unsigned long long  max_64bits = 0xFFFFFFFFFFFFFFFFULL;
00176   
00177   hdrlen = sizeof(def_lct_hdr_t);
00178   
00179   memset(pkt, 0, MAX_PACKET_LENGTH);
00180   def_lct_hdr = (def_lct_hdr_t*)pkt;
00181   
00182   def_lct_hdr->version = ALC_VERSION;
00183   def_lct_hdr->flag_c = 0;
00184   def_lct_hdr->reserved = 0;
00185   def_lct_hdr->flag_t = 0;
00186   def_lct_hdr->flag_r = 0;
00187   
00188   def_lct_hdr->flag_a = 0;
00189   def_lct_hdr->flag_b = 0; /* TODO */
00190   
00191   def_lct_hdr->codepoint = fec_enc_id;
00192 
00193   def_lct_hdr->cci = htonl(0);
00194   
00195   if(s->half_word) {
00196                 if(((s->tsi <= max_16bits) && (toi <= max_16bits))) {
00197                         def_lct_hdr->flag_s = 0;
00198                         def_lct_hdr->flag_o = 0;
00199                         def_lct_hdr->flag_h = 1;
00200 
00201                         half_word1 = (unsigned short)s->tsi;
00202                         half_word2 = (unsigned short)toi;
00203                         
00204                         word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
00205                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00206                         hdrlen += 4;
00207                 }
00208                 else if(((((s->tsi <= max_16bits) && (((toi > max_16bits) && (toi <= max_32bits))))) ||
00209                          (((toi <= max_16bits) && (((s->tsi > max_16bits) && (s->tsi <= max_32bits))))))) {
00210                         def_lct_hdr->flag_s = 1;
00211                         def_lct_hdr->flag_o = 1;
00212                         def_lct_hdr->flag_h = 0;
00213 
00214                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
00215                         hdrlen += 4;
00216 
00217                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
00218                         hdrlen += 4;    
00219                 }
00220                 else if((((s->tsi > max_16bits) && (s->tsi <= max_32bits))) &&
00221                          (((toi > max_16bits) && (toi <= max_32bits)))) {                       
00222                         def_lct_hdr->flag_s = 1;
00223                         def_lct_hdr->flag_o = 1;
00224                         def_lct_hdr->flag_h = 0;
00225 
00226                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
00227                         hdrlen += 4;
00228 
00229                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
00230                         hdrlen += 4;
00231                 }
00232                 else if(((s->tsi <= max_16bits) && (((toi > max_32bits) && (toi <= max_48bits))))) {            
00233                         def_lct_hdr->flag_s = 0;
00234                         def_lct_hdr->flag_o = 1;
00235                         def_lct_hdr->flag_h = 1;
00236 
00237                         half_word1 = (unsigned short)s->tsi;
00238                         half_word2 = (unsigned short)((toi >> 32) & 0x0000FFFF);
00239                         word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
00240                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00241                         hdrlen += 4;
00242                         
00243                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
00244                         hdrlen += 4;
00245                 }
00246                 else if(((toi < max_16bits) && (((s->tsi > max_32bits) && (s->tsi <= max_48bits))))) {
00247 
00248                         def_lct_hdr->flag_s = 1;
00249                         def_lct_hdr->flag_o = 0;
00250                         def_lct_hdr->flag_h = 1;
00251 
00252                         word = (unsigned int)((s->tsi >> 16) & 0xFFFFFFFF);
00253                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00254                         hdrlen += 4;
00255                 
00256                         half_word1 = (unsigned short)(s->tsi & 0x0000FFFF);
00257                         half_word2 = (unsigned short)toi;
00258 
00259                         word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
00260                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00261                         hdrlen += 4;
00262                 }
00263                 else if((((s->tsi > max_32bits) && (s->tsi <= max_48bits))) &&
00264                          (((toi > max_32bits) && (toi <= max_48bits)))) {               
00265                         def_lct_hdr->flag_s = 1;
00266                         def_lct_hdr->flag_o = 1;
00267                         def_lct_hdr->flag_h = 1;
00268 
00269                         word = (unsigned int)((s->tsi >> 16) & 0xFFFFFFFF);
00270                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00271                         hdrlen += 4;
00272                 
00273                         half_word1 = (unsigned short)(s->tsi & 0x0000FFFF);
00274                         half_word2 = (unsigned short)((toi >> 32) & 0x0000FFFF);
00275                         word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
00276                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00277                         hdrlen += 4;
00278                         
00279                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
00280                         hdrlen += 4;
00281                 }
00282                 else if((((s->tsi > max_16bits) && (s->tsi <= max_32bits))) &&
00283                          (((toi > max_32bits) && (toi <= max_64bits)))) {
00284                         def_lct_hdr->flag_s = 1;
00285                         def_lct_hdr->flag_o = 2;
00286                         def_lct_hdr->flag_h = 0;
00287 
00288                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
00289                         hdrlen += 4;
00290 
00291                         word = (unsigned int)((toi >> 32) & 0xFFFFFFFF);
00292                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00293                         hdrlen += 4;
00294 
00295                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
00296                         hdrlen += 4;
00297                 }
00298                 else if(((s->tsi < max_16bits) && ((toi > max_48bits) && (toi <= max_64bits)))) {
00299                         def_lct_hdr->flag_s = 1;
00300                         def_lct_hdr->flag_o = 2;
00301                         def_lct_hdr->flag_h = 0;
00302 
00303                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
00304                         hdrlen += 4;
00305 
00306                         word = (unsigned int)((toi >> 32) & 0xFFFFFFFF);
00307                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00308                         hdrlen += 4;
00309 
00310                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
00311                         hdrlen += 4;
00312                 }
00313                 else {
00314                         printf("TSI & TOI field combination not supported!\n");
00315                         fflush(stdout);
00316                         return -1;
00317                 }
00318         }
00319         else {
00320                 def_lct_hdr->flag_s = 1;
00321                 def_lct_hdr->flag_h = 0;
00322         
00323                 *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)s->tsi);
00324                 hdrlen += 4;
00325 
00326                 if(toi <= max_32bits) {
00327                         def_lct_hdr->flag_o = 1;
00328                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
00329                         hdrlen += 4;
00330                 }
00331                 else if(((toi > max_32bits) && (toi <= max_64bits))) {
00332                         def_lct_hdr->flag_o = 2;
00333                 
00334                         word = (unsigned int)((toi >> 32) & 0xFFFFFFFF);
00335                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00336                         hdrlen += 4;
00337                 
00338                         *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)toi);
00339                         hdrlen += 4;
00340                 }
00341                 else {
00342                         printf("TSI & TOI field combination not supported!\n");
00343                         fflush(stdout);
00344                         return -1;
00345                 }
00346         }
00347 
00348         if(toi == FDT_TOI) {
00349           hdrlen += add_fdt_lct_he(def_lct_hdr, hdrlen, s->fdt_instance_id);
00350                 
00351 #ifdef USE_ZLIB
00352           if(s->encode_content == ZLIB_FDT || s->encode_content == ZLIB_FDT_AND_GZIP_FILES ) {
00353             hdrlen += add_cenc_lct_he(def_lct_hdr, hdrlen, (unsigned char)ZLIB);
00354           }     
00355 #endif
00356           
00357         }
00358         
00359         if(((toi == FDT_TOI) || (s->use_fec_oti_ext_hdr == 1))) {
00360           
00361           if(fec_enc_id == COM_NO_C_FEC_ENC_ID) {
00362             
00363             hdrlen += add_fti_0_2_128_130_lct_he(def_lct_hdr, hdrlen, transfer_len, 0,
00364                                                  es_len, max_sb_len);
00365           }
00366           else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
00367             
00368             hdrlen += add_fti_0_2_128_130_lct_he(def_lct_hdr, hdrlen, transfer_len, 0,
00369                                                  es_len, max_sb_len);
00370           }
00371           else if(fec_enc_id == RS_FEC_ENC_ID) {
00372             
00373             hdrlen += add_fti_3_lct_he(def_lct_hdr, hdrlen, transfer_len, (unsigned char)GF_BITS,
00374                                        (unsigned char)1, es_len,
00375                                        (unsigned short)tr_block->max_k, (unsigned short)tr_block->max_n);
00376           }
00377           else if((fec_enc_id == COM_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID)) {
00378             
00379             hdrlen += add_fti_0_2_128_130_lct_he(def_lct_hdr, hdrlen, transfer_len, fec_inst_id,
00380                                                  es_len, max_sb_len);   
00381           }
00382           
00383           else if(fec_enc_id == SB_SYS_FEC_ENC_ID) {
00384             
00385             hdrlen += add_fti_129_lct_he(def_lct_hdr, hdrlen, transfer_len, fec_inst_id,
00386                                          es_len, (unsigned short)tr_block->max_k, (unsigned short)tr_block->max_n);
00387           }
00388         }
00389         
00390         /* TODO: add other LCT header extensions here */
00391         /*if(nop) {
00392           hdrlen += add_nop_lct_he();
00393           }
00394           if(auth) {
00395           hdrlen += add_auth_lct_he();
00396           }
00397           if(time) {
00398           hdrlen += add_time_lct_he();
00399           }
00400         */
00401         
00402         def_lct_hdr->hdr_len = hdrlen >> 2; /* Header length in 32-bit words */ 
00403         *(unsigned short*)def_lct_hdr = htons(*(unsigned short*)def_lct_hdr);
00404 
00405         /* FEC Payload ID */
00406 
00407         if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))) {
00408           
00409           hdrlen += add_alc_fpi_0_130(def_lct_hdr, hdrlen, (unsigned short)tr_block->sbn,
00410                                       (unsigned short)tr_unit->esi);    
00411         }
00412         else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
00413           
00414           hdrlen += add_alc_fpi_2_128(def_lct_hdr, hdrlen, tr_block->sbn, tr_unit->esi);
00415         }
00416         else if(fec_enc_id == RS_FEC_ENC_ID) {
00417           
00418           hdrlen += add_alc_fpi_3(def_lct_hdr, hdrlen, tr_block->sbn,
00419                                   tr_unit->esi, GF_BITS);
00420         }
00421         else if(fec_enc_id == SB_LB_E_FEC_ENC_ID) {
00422           
00423           hdrlen += add_alc_fpi_2_128(def_lct_hdr, hdrlen, tr_block->sbn, tr_unit->esi);
00424         }
00425         else if(fec_enc_id == SB_SYS_FEC_ENC_ID) {
00426           
00427           hdrlen += add_alc_fpi_129(def_lct_hdr, hdrlen, tr_block->sbn,
00428                                     (unsigned short)tr_block->k,
00429                                     (unsigned short)tr_unit->esi);
00430         }
00431 
00432         memcpy(pkt + hdrlen, tr_unit->data, tr_unit->len);
00433         sendlen = hdrlen + tr_unit->len;
00434 
00435         if(ch != NULL) {
00436 
00437                 if (ch->s->calculate_session_size == FALSE) {
00438 
00439                         /*if(toi == 0 && tr_block->sbn == 0 && tr_unit->esi == 0) {
00440                         }
00441                         else {*/
00442                   sendto(ch->tx_sock, (char *)pkt, sendlen, 0,          
00443                     ch->addrinfo->ai_addr, ch->addrinfo->ai_addrlen);
00444                         /*}*/
00445                 }
00446                 
00447                 add_session_sent_bytes(s->s_id, sendlen);
00448 
00449                 /* Should we take UDP/IP headers into account? */
00450                 /* UDP */
00451                 add_session_sent_bytes(s->s_id, 8);
00452                 /* IPv4 or IPv6 */
00453                 if(s->addr_family == PF_INET) {
00454                   add_session_sent_bytes(s->s_id, 20);
00455                 }
00456                 else {
00457                   add_session_sent_bytes(s->s_id, 40);
00458                 }
00459         }
00460         else {
00461                 if(!(sendbuf = (unsigned char*)calloc((sendlen + 1), sizeof(unsigned char)))) {
00462                         printf("Could not alloc memory for tx queue packet!\n");
00463                         fflush(stdout);
00464                         return -1;
00465                 }
00466 
00467                 memcpy(sendbuf, pkt, sendlen);
00468 
00469                 while(1) {
00470 
00471                         if(s->state == SExiting) {
00472                                 return -2;
00473                         }
00474 
00475                         if(add_pkt_to_tx_queue(s, sendbuf, sendlen) > 0) {
00476                                 break;
00477                         }
00478                         else {
00479 #ifdef _MSC_VER
00480                                 Sleep(10);
00481 #else
00482                                 usleep(10000);
00483 #endif
00484                         }
00485                 }
00486         }
00487           
00488         return sendlen;
00489 }
00490 
00500 int calculate_packet_length(alc_session_t *s) {
00501 
00502         int packet_length = 0;
00503 
00504         if(s->addr_family == PF_INET) {
00505 
00506                 if(s->use_fec_oti_ext_hdr == 1) {
00507 
00508                         /* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */
00509 
00510                         if(((s->def_fec_enc_id == COM_NO_C_FEC_ENC_ID) ||
00511                                 (s->def_fec_enc_id == COM_FEC_ENC_ID) ||
00512                                 (s->def_fec_enc_id == RS_FEC_ENC_ID))) {                
00513                                 packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 20); 
00514                         }
00515                         else if(((s->def_fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) ||
00516                                  (s->def_fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00517                                  (s->def_fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00518                                 packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 20); 
00519                         }
00520                 }
00521                 else if(s->use_fec_oti_ext_hdr == 0) {
00522                         /* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */ 
00523 
00524                         if(((s->def_fec_enc_id == COM_NO_C_FEC_ENC_ID) ||
00525                                 (s->def_fec_enc_id == COM_FEC_ENC_ID) ||
00526                                 (s->def_fec_enc_id == RS_FEC_ENC_ID))) {        
00527                                 packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 20); 
00528                         }
00529                         else if(((s->def_fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) ||
00530                                  (s->def_fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00531                                  (s->def_fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00532                                 packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 20); 
00533                         }
00534                 }
00535         }
00536         else if(s->addr_family == PF_INET6) {
00537                 if(s->use_fec_oti_ext_hdr == 1) {
00538                         /* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */
00539 
00540                         if(((s->def_fec_enc_id == COM_NO_C_FEC_ENC_ID) ||
00541                                 (s->def_fec_enc_id == COM_FEC_ENC_ID) ||
00542                                 (s->def_fec_enc_id == RS_FEC_ENC_ID))) {                
00543                                 packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 40); 
00544                         }
00545                         else if(((s->def_fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) ||
00546                                  (s->def_fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00547                                  (s->def_fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00548                                 packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 40); 
00549                         }
00550                 }
00551                 else if(s->use_fec_oti_ext_hdr == 0) {
00552                         /* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */
00553 
00554                         if(((s->def_fec_enc_id == COM_NO_C_FEC_ENC_ID) ||
00555                                 (s->def_fec_enc_id == COM_FEC_ENC_ID) ||
00556                                 (s->def_fec_enc_id == RS_FEC_ENC_ID))) {                
00557                                 packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 20); 
00558                         }
00559                         else if(((s->def_fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) ||
00560                                  (s->def_fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00561                                  (s->def_fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00562                                 packet_length =  s->def_eslen + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 20); 
00563                         }
00564                 }
00565         }
00566 
00567         return packet_length;   
00568 }
00569 
00579 float session_kbit_rate(const alc_session_t *s) {
00580 
00581     double curr_time;
00582     float actual_kbit_rate = (float)s->def_tx_rate;
00583     struct timeb timeb_current_time;
00584 
00585     ftime(&timeb_current_time);
00586 
00587     curr_time = timeb_current_time.time+timeb_current_time.millitm/1000.0;
00588 
00589     if(s->sent_bytes > 0 && curr_time > s->ftimestarttime) {
00590         actual_kbit_rate = (float)((s->sent_bytes*8/1024.0) / (curr_time - s->ftimestarttime));
00591     }
00592 
00593     /*printf("\n%f", curr_time-s->ftimestarttime);
00594     printf(" %f", actual_kbit_rate);*/
00595     return actual_kbit_rate;
00596 }
00597 
00598 int alc_send(int s_id, int tx_mode, char *buf, int buf_len,
00599                          unsigned long long toi, unsigned long long transfer_len,
00600                          unsigned short es_len, unsigned int max_sb_len, unsigned int sbn,
00601                          unsigned char fec_enc_id, unsigned short fec_inst_id) {
00602 
00603         trans_block_t *tr_block = NULL;
00604         trans_unit_t *tr_unit = NULL;
00605         unsigned int i = 0;
00606 
00607         alc_channel_t *ch = NULL;
00608         alc_session_t *s = NULL;
00609 
00610         int sent = 0;
00611         int tb_data_left = 0;
00612 
00613         int packet_length = 0;
00614         int addr_family = 0;
00615         int use_fec_oti_ext_hdr = 0;
00616         double loss_prob = 0;
00617         int retval = 0;
00618         double tx_percent = 0;
00619 
00620         
00621     double packetpersec = 0;
00622     double interval = 0;
00623     double block_interval = 0;
00624     long sleep_interval = 0;
00625     float diff_kbit_rate = 0;
00626     double relative_error = 0;
00627     double correction = 0;
00628 
00629         s = get_alc_session(s_id);
00630 
00631         if(tx_mode != TX_THREAD) { /* We have only the base channel in this case */
00632                 ch = s->ch_list[0]; /* Let's take the base channel */
00633                 addr_family = s->addr_family;
00634                 use_fec_oti_ext_hdr = s->use_fec_oti_ext_hdr;
00635 
00636                 if(toi == FDT_TOI) {
00637 
00638                         /* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FDT + EXT_CENC + EXT_FTI + FEC_PL_ID + UDP + IP */ 
00639 
00640                         if(addr_family == PF_INET) {
00641 
00642                                 if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
00643                                         || (fec_enc_id == RS_FEC_ENC_ID))) {
00644                                                 packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 4 + 8 + 20); 
00645                                 }
00646                                 else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00647                                         (fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00648                                                 packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 8 + 8 + 20); 
00649                                 }
00650                         }
00651                         else if(addr_family == PF_INET6) {
00652 
00653                                 if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
00654                                         || (fec_enc_id == RS_FEC_ENC_ID))) {
00655                                                 packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 4 + 8 + 40); 
00656                                 }
00657                                 else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00658                                         (fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00659                                                 packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 8 + 8 + 40); 
00660                                 }
00661                         }
00662                 }
00663                 else {
00664                         if(addr_family == PF_INET) {
00665 
00666                                 if(use_fec_oti_ext_hdr == 1) {
00667                                         /* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */ 
00668 
00669                                         if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
00670                                                 || (fec_enc_id == RS_FEC_ENC_ID))) {
00671                                                         packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 20); 
00672                                         }
00673                                         else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00674                                                 (fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00675                                                         packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 20); 
00676                                         }
00677                                 }
00678                                 else if(use_fec_oti_ext_hdr == 0) {
00679 
00680                                         /* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */ 
00681 
00682                                         if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
00683                                                 || (fec_enc_id == RS_FEC_ENC_ID))) {
00684                                                         packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 20); 
00685                                         }
00686                                         else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00687                                                 (fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00688                                                         packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 20); 
00689                                         }
00690                                 }
00691                         }
00692                         else if(addr_family == PF_INET6) {
00693 
00694                                 if(use_fec_oti_ext_hdr == 1) {
00695                                         /* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */ 
00696 
00697                                         if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
00698                                                 || (fec_enc_id == RS_FEC_ENC_ID))) {
00699                                                         packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 40); 
00700                                         }
00701                                         else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00702                                                 (fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00703                                                         packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 40); 
00704                                         }
00705                                 }
00706                                 else if(use_fec_oti_ext_hdr == 0) {
00707 
00708                                         /* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */ 
00709 
00710                                         if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID)
00711                                                 || (fec_enc_id == RS_FEC_ENC_ID))) {
00712                                                         packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 40); 
00713                                         }
00714                                         else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) ||
00715                                                 (fec_enc_id == SB_SYS_FEC_ENC_ID))) {
00716                                                         packet_length =  es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 40); 
00717                                         }
00718                                 }
00719                         }
00720                 }
00721         }
00722 
00723         if(fec_enc_id == COM_NO_C_FEC_ENC_ID) {
00724                 tr_block = null_fec_encode_src_block(buf, buf_len, sbn, es_len);
00725         }
00726         else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) {
00727                 tr_block = xor_fec_encode_src_block(buf, buf_len, sbn, es_len);
00728         }
00729         else if(fec_enc_id == RS_FEC_ENC_ID) {
00730                 tr_block = rs_fec_encode_src_block(buf, buf_len, sbn, es_len, s->def_fec_ratio,
00731                         max_sb_len);
00732         }
00733         else if(((fec_enc_id == SB_SYS_FEC_ENC_ID) && (fec_inst_id == REED_SOL_FEC_INST_ID))) {
00734                 tr_block = rs_fec_encode_src_block(buf, buf_len, sbn, es_len, s->def_fec_ratio,
00735                         max_sb_len);
00736         }
00737         else {
00738                 if(fec_enc_id < 128) {
00739                         printf("FEC Encoding %i is not supported!\n", fec_enc_id);
00740                 }
00741                 else {
00742                         printf("FEC Encoding %i/%i is not supported!\n", fec_enc_id, fec_inst_id);
00743                 }
00744 
00745                 return -1; 
00746         }
00747 
00748         if(tr_block == NULL) {
00749                 return -1;
00750         }
00751 
00752         if(tx_mode != TX_THREAD) {
00753 
00754                 tb_data_left = es_len * tr_block->n;
00755                 tr_unit = tr_block->unit_list; 
00756 
00757                 for(i = 0; i < tr_block->n; i++) {
00758 
00759                         if(s->state == SPaused) {
00760                                 while(1) {
00761                                         if(s->state == SExiting) {
00762                                                 return -2;
00763                                         }
00764                           
00765                                         if(s->state == SActive) {
00766                                                 break;
00767                                         }
00768 #ifdef _MSC_VER
00769                                         Sleep(1000);
00770 #else
00771                                         usleep(1000000);
00772 #endif
00773                                 }
00774                         }
00775 
00776                         if(s->state == SExiting) {
00777                                 while(1) {
00778                                         free(tr_unit->data);
00779 
00780                                         if(tr_unit->esi == (tr_block->n - 1)) {
00781                                                 break;
00782                                         }
00783                                         tr_unit++;
00784                                 }
00785 
00786                                 free(tr_block->unit_list);
00787                                 free(tr_block);
00788 
00789                                 return -2;
00790                         }
00791 
00792                         if (ch->s->calculate_session_size == FALSE) {
00793                                 packetpersec =
00794                                         ((double)(ch->tx_rate * 1000) / (double)(packet_length * 8));   
00795                                 interval = ((double)1 / packetpersec);
00796                                 block_interval = /*tr_block->n*/ 1*interval;
00797                                 sleep_interval = (long)(block_interval*1000);
00798                                 diff_kbit_rate = session_kbit_rate(ch->s)-ch->s->def_tx_rate;
00799                                 relative_error = (double)diff_kbit_rate/(double)ch->s->def_tx_rate;
00800                                 correction = 1;
00801 
00802                                 //printf("\n%f ", relative_error);
00803                                 if(relative_error > 0.001) {
00804                                         correction = 1.0 + (relative_error*50.0);
00805                                 }
00806                                 else if(relative_error < -0.001) {
00807                                         relative_error = -relative_error;
00808                                         correction = 1.0 - (relative_error*50.0);
00809                                 }
00810 
00811                                 //printf("%f ", correction);
00812                                 //printf("%d ", sleep_interval);
00813 
00814                                 // Adjust the sleep interval according the diff_bit_rate value.
00815                                 sleep_interval = sleep_interval*correction;
00816                                 //printf("%d", sleep_interval);
00817 
00818                                 if(sleep_interval > 0) {
00819 #ifdef _MSC_VER
00820                                         Sleep(sleep_interval);
00821 #else
00822                                         usleep(sleep_interval*1000);
00823 #endif
00824                                 }
00825                         }
00826 
00827                         loss_prob = 0;
00828 
00829                         if(s->simul_losses) {
00830                                 if(ch->previous_lost == TRUE) {
00831                                         loss_prob = s->loss_ratio2;
00832                                 }
00833                                 else {
00834                                         loss_prob = s->loss_ratio1;
00835                                 }
00836                         }
00837 
00838                         if(!randomloss(loss_prob)) {
00839 
00840                                 retval = send_unit(tr_unit, tr_block, s, ch, toi, transfer_len, max_sb_len, es_len,
00841                                         fec_enc_id, fec_inst_id);
00842 
00843                                 if(retval < 0) {
00844 
00845                                         while(1) {
00846 
00847                                                 free(tr_unit->data);
00848 
00849                                                 if(tr_unit->esi == (tr_block->n - 1)) {
00850                                                         break;
00851                                                 }
00852 
00853                                                 tr_unit++;
00854                                         }
00855 
00856                                         free(tr_block->unit_list);
00857                                         free(tr_block);
00858 
00859                                         return -1;
00860                                 }
00861 
00862                                 sent += tr_unit->len;
00863 
00864                                 add_object_sent_bytes(s_id, tb_data_left < tr_unit->len ?
00865                                         (unsigned int)tb_data_left : tr_unit->len);
00866 
00867                                 tb_data_left -= tb_data_left < tr_unit->len ? tb_data_left : tr_unit->len;
00868 
00869                                 if(((toi == FDT_TOI && s->verbosity == 4) || (toi != FDT_TOI && s->verbosity > 1))) {
00870 
00871                                         tx_percent = (double)((double)(100 *
00872                                                 ((double)(long long)get_object_sent_bytes(s_id)/
00873                                                 (double)(long long)transfer_len)));
00874 
00875                                         if(((tx_percent >= (get_object_last_print_tx_percent(s_id) + 1))
00876                                                 || (tx_percent == 100))) {
00877                                                         set_object_last_print_tx_percent(s_id, tx_percent);
00878                                                         printf("%.2f%% of object sent (TOI=%llu)\n", tx_percent, toi);
00879                                         }
00880 
00881                                         fflush(stdout);
00882                                 }
00883 
00884                                 ch->previous_lost = FALSE;
00885                         }
00886                         else {
00887                                 ch->previous_lost = TRUE;
00888                         }
00889 
00890 
00891                         free(tr_unit->data);
00892                         tr_unit++;
00893                 }
00894 
00895                 free(tr_block->unit_list);
00896                 free(tr_block);
00897         }
00898         else {
00899                 tr_unit = tr_block->unit_list;
00900 
00901                 for(i = 0; i < tr_block->n; i++) {
00902 
00903                         retval = send_unit(tr_unit, tr_block, s, NULL, toi, transfer_len,
00904                                 max_sb_len, es_len, fec_enc_id, fec_inst_id);
00905 
00906                         if(retval == -1) {
00907                                 i--;
00908                                 continue;
00909                         }
00910                         else if(retval == -2) {
00911 
00912                                 while(1) {
00913 
00914                                         free(tr_unit->data);
00915 
00916                                         if(tr_unit->esi == (tr_block->n - 1)) {
00917                                                 break;
00918                                         }
00919 
00920                                         tr_unit++;
00921                                 }
00922 
00923                                 free(tr_block->unit_list);
00924                                 free(tr_block);
00925 
00926                                 return retval;          
00927                         }
00928 
00929                         free(tr_unit->data);
00930                         tr_unit++;
00931                 }
00932 
00933                 free(tr_block->unit_list);
00934                 free(tr_block);
00935         }
00936 
00937         return sent;
00938 }
00939 
00940 int send_session_close_packet(int s_id) {
00941 
00942         int     sendlen;                             /* number of bytes to send */
00943         int     hdrlen;                                 /* length of total ALC header */
00944         int retval = 0;
00945 
00946         alc_channel_t *ch;
00947 
00948         unsigned char sendbuf[MAX_PACKET_LENGTH];       /* TU (hdrs+data) cannot be larger */
00949 
00950         def_lct_hdr_t *def_lct_hdr;
00951         
00952         unsigned short half_word1;
00953         unsigned short half_word2;
00954         unsigned int word;
00955 
00956         assert(get_alc_session(s_id)!=NULL);
00957         ch = get_alc_session(s_id)->ch_list[0]; /* We send the close packet only to the base channel */
00958         
00959         memset(sendbuf, 0, MAX_PACKET_LENGTH);
00960         def_lct_hdr = (def_lct_hdr_t*)sendbuf;
00961 
00962         def_lct_hdr->version = ALC_VERSION;
00963         def_lct_hdr->flag_c = 0;
00964         def_lct_hdr->reserved = 0;
00965 
00966         def_lct_hdr->flag_t = 0;
00967         def_lct_hdr->flag_r = 0;
00968         def_lct_hdr->flag_a = 1;
00969         def_lct_hdr->flag_b = 0;
00970         def_lct_hdr->codepoint = ch->s->def_fec_enc_id; 
00971 
00972         def_lct_hdr->cci = htonl(0);
00973 
00974         hdrlen = sizeof(def_lct_hdr_t);
00975         
00976         if(ch->s->tsi <= 0xFFFFFFFF) {
00977                 
00978                 def_lct_hdr->flag_s = 1;
00979                 def_lct_hdr->flag_o = 0;
00980                 def_lct_hdr->flag_h = 0;
00981                 
00982                 *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl((unsigned int)ch->s->tsi);
00983                 hdrlen += 4;
00984         }
00985         else {
00986                 /* TSI field length 48 bits not possible without TOI field */
00987 
00988                 def_lct_hdr->flag_s = 1;
00989                 def_lct_hdr->flag_o = 0;
00990                 def_lct_hdr->flag_h = 1;
00991 
00992                 word = (unsigned int)((ch->s->tsi >> 16) & 0xFFFFFFFF);
00993                 *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
00994                 hdrlen += 4;
00995         
00996                 half_word1 = (unsigned short)(ch->s->tsi & 0x0000FFFF);
00997                 half_word2 = (unsigned short)0;
00998 
00999                 word = ((half_word1 << 16) | (half_word2 & 0xFFFF));
01000                 *(unsigned int*)((unsigned char*)def_lct_hdr + hdrlen) = htonl(word);
01001                 hdrlen += 4;
01002         }
01003 
01004         def_lct_hdr->hdr_len = hdrlen >> 2; /* Header length in 32-bit words */ 
01005         *(unsigned short*)def_lct_hdr = htons(*(unsigned short*)def_lct_hdr);
01006 
01007         sendlen = hdrlen;
01008 
01009         if(ch->s->cc_id == RLC) {
01010                 retval = mad_rlc_fill_header(ch->s, (rlc_hdr_t*)(sendbuf + 4), ch->ch_id);
01011         }
01012                         
01013         retval = sendto(ch->tx_sock, (char *)sendbuf, sendlen, 0,                               
01014                 ch->addrinfo->ai_addr, ch->addrinfo->ai_addrlen);
01015 
01016         add_session_sent_bytes(s_id, sendlen);
01017 
01018         /* Should we take UDP/IP headers into account? */
01019         /* UDP */
01020         add_session_sent_bytes(s_id, 8);
01021         /* IPv4 or IPv6 */
01022         if(ch->s->addr_family == PF_INET) {
01023           add_session_sent_bytes(s_id, 20);
01024         }
01025         else {
01026           add_session_sent_bytes(s_id, 40);
01027         }
01028 
01029         return retval;
01030 }
01031 
01032 void* tx_thread(void *s) {
01033 
01034   alc_session_t *session;
01035   alc_channel_t *channel;
01036   tx_queue_t *tmp_ptr;
01037   
01038   tx_queue_t *next_pkt;
01039   tx_queue_t *pkt;
01040   
01041   int i, j;
01042   int retcode;
01043   int packet_length;
01044   
01045   double interval;
01046   double packetpersec;
01047   double currenttime;
01048   double lasttime;
01049   
01050   double loss_prob;
01051   
01052   session = (alc_session_t *)s;
01053   
01054   packet_length = calculate_packet_length(session);
01055   
01056   packetpersec = ((double)(session->def_tx_rate * 1000) / (double)(packet_length * 8));   
01057   interval = ((double)1 / packetpersec);
01058   
01059   /* interval is too small for FDT Instance, because in packet length calculation FDT Instance's
01060      extra header fields are not counted */
01061   
01062   while(session->state == SActive) {    
01063     
01064     if(session->tx_queue_begin == NULL) {
01065 #ifdef _MSC_VER
01066       Sleep(1);
01067 #else
01068       usleep(1000);
01069 #endif          
01070       continue;
01071     }
01072     else {
01073       break;
01074     }
01075   }
01076   
01077   lasttime = sec();
01078   
01079   while(session->state == SActive) {
01080     
01081     currenttime = sec();
01082     
01083         if(session->calculate_session_size == FALSE) {
01084 
01085                 while(currenttime < (lasttime + interval)) {
01086       
01087                         if(session->optimize_tx_rate) {
01088 #ifdef _MSC_VER
01089                                 Sleep(0);
01090 #else
01091                                 usleep(0);
01092 #endif
01093                         }
01094                         else {
01095 #ifdef _MSC_VER
01096                                 Sleep(1);
01097 #else
01098                                 usleep(1000);
01099 #endif
01100                         }
01101                         currenttime = sec();
01102                 }
01103         }    
01104     for(i = 0; i < session->nb_channel; i++) {
01105       
01106       channel = session->ch_list[i];
01107       
01108       if(session->cc_id == RLC) {
01109         
01110         if(channel->start_sending == FALSE) {
01111           continue;
01112         }
01113         
01114         if(channel->wait_after_sp > 0) {
01115           channel->wait_after_sp--;
01116           continue;
01117         }
01118       }
01119       
01120       for(j = 0; j < channel->nb_tx_units; j++) {
01121         
01122         if(channel->queue_ptr == NULL) {
01123           
01124           if(channel->ready == FALSE) {
01125             session->nb_ready_channel++;
01126             channel->ready = TRUE;
01127           }
01128           
01129           if(session->nb_ready_channel == session->nb_sending_channel) {
01130             
01131             pkt = session->tx_queue_begin;
01132             
01133             while(pkt != NULL) {
01134               next_pkt = pkt->next;
01135               free(pkt->data);
01136               free(pkt);
01137               pkt = next_pkt;
01138             }   
01139             
01140             session->tx_queue_begin = NULL;
01141             session->tx_queue_size = 0;
01142           }
01143           
01144           break;
01145         }
01146         
01147         if(session->first_unit_in_loop) {
01148           
01149           if(session->cc_id == RLC) {
01150             mad_rlc_reset_tx_sp(session);
01151           }
01152           
01153           session->first_unit_in_loop = FALSE;
01154         }
01155         if(session->cc_id == RLC) {
01156           
01157           retcode = mad_rlc_fill_header(session, (rlc_hdr_t*)(channel->queue_ptr->data + 4),
01158                                         channel->ch_id);
01159           
01160           if(retcode < 0) {
01161           }
01162         }
01163         
01164         loss_prob = 0;
01165         
01166         if(session->simul_losses) {
01167           if(channel->previous_lost == TRUE) {
01168             loss_prob = channel->s->loss_ratio2; /*P_LOSS_WHEN_LOSS;*/
01169           }
01170           else {
01171             loss_prob = channel->s->loss_ratio1; /*P_LOSS_WHEN_OK;*/
01172           }
01173         }
01174         
01175         if(!randomloss(loss_prob)) {
01176         
01177           if(session->calculate_session_size == FALSE) {
01178             retcode = sendto(channel->tx_sock, (char*)channel->queue_ptr->data, 
01179                              channel->queue_ptr->datalen, 0, channel->addrinfo->ai_addr,
01180                              channel->addrinfo->ai_addrlen);
01181             
01182             if(retcode < 0) {
01183               
01184 #ifdef _MSC_VER
01185               printf("sendto failed with: %d\n", WSAGetLastError());
01186 #else
01187               printf("sendto failed with: %d\n", errno);
01188 #endif
01189               break;
01190             }
01191           }
01192           
01193           add_session_sent_bytes(session->s_id, channel->queue_ptr->datalen);
01194           /* Should we take UDP/IP headers into account? */
01195           /* UDP */
01196           add_session_sent_bytes(session->s_id, 8);
01197           /* IPv4 or IPv6 */
01198           if(session->addr_family == PF_INET) {
01199             add_session_sent_bytes(session->s_id, 20);
01200           }
01201           else {
01202             add_session_sent_bytes(session->s_id, 40);
01203           }
01204           
01205           channel->previous_lost = FALSE;
01206         }
01207         else {
01208           channel->previous_lost = TRUE;
01209         }
01210         
01211         channel->queue_ptr->nb_tx_ch++;
01212         
01213         if(channel->queue_ptr->nb_tx_ch == (unsigned int)session->nb_channel) {
01214           
01215           tmp_ptr = channel->queue_ptr->next;
01216           free(channel->queue_ptr->data);
01217           free(channel->queue_ptr);
01218           
01219           channel->queue_ptr = tmp_ptr;
01220           session->tx_queue_begin = tmp_ptr;
01221           session->tx_queue_size--;
01222         }
01223         else {
01224           channel->queue_ptr = channel->queue_ptr->next;
01225         }
01226       }
01227     }
01228     
01229     lasttime += interval;
01230   }
01231 
01232 #ifdef _MSC_VER
01233   _endthread();
01234 #else
01235   pthread_exit(0);
01236 #endif
01237 
01238   return NULL;
01239 }

Generated on Fri Mar 9 20:08:51 2007 for MAD-FCL by  doxygen 1.5.0