📄 alc_tx.c
字号:
/* $Author: peltotas $ $Date: 2006/03/16 13:02:07 $ $Revision: 1.79 $ *//* * MAD-ALCLIB: Implementation of ALC/LCT protocols, Compact No-Code FEC, * Simple XOR FEC, Reed-Solomon FEC, and RLC Congestion Control protocol. * Copyright (c) 2003-2006 TUT - Tampere University of Technology * main authors/contacts: jani.peltotalo@tut.fi and sami.peltotalo@tut.fi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "inc.h"/**** Private functions ****/int calculate_packet_length(alc_session_t *s);int send_unit(trans_unit_t *tr_unit, trans_block_t *tr_block, alc_session_t *s, alc_channel_t *ch,#ifdef WIN32 ULONGLONG toi, ULONGLONG toilen,#else unsigned long long toi, unsigned long long toilen,#endif unsigned int max_sblen, unsigned short eslen, unsigned char fec_enc_id, unsigned short fec_inst_id);int add_pkt_to_tx_queue(alc_session_t *s, unsigned char *sendbuf, unsigned int sendlen);/* * This function sends source block from object to channel or tx_queue. * * Params: int *s_id: Pointer to Session identifier, * int *ch_id: Pointer to Channel identifier (if NULL use queue mode), * char *buf: Pointer to data to be sent, * ULONGLONG/unsigned long long buf_len: Lenght of data to be sent, * ULONGLONG/unsigned long long toi: Transport Object Identifier, * ULONGLONG/unsigned long long toilen: Length of transport object, * unsigned short eslen: Encoding Symbol Length, * unsigned int max_sblen: Maximum-Size Source Block Length, * unsigned int sbn: Souirce Block Number, * unsigned char fec_enc_id: FEC Encoding ID, * unsigned short fec_inst_id: FEC Instance ID, * int is_last_block: is this last block for object (1 = yes, 0 = no). * * Return: int: 0 after succesfull sending, -1 otherwise * */int alc_send(int *s_id, int *ch_id, char *buf, int buf_len,#ifdef WIN32 ULONGLONG toi, ULONGLONG toi_len,#else unsigned long long toi, unsigned long long toi_len,#endif unsigned short es_len, unsigned int max_sb_len, unsigned int sbn, unsigned char fec_enc_id, unsigned short fec_inst_id) { trans_block_t *tr_block = NULL; trans_unit_t *tr_unit = NULL; unsigned int i = 0; alc_channel_t *ch = NULL; alc_session_t *s = NULL; int sent = 0; int tb_data_left = 0; int packet_length = 0; double interval = 0; double packetpersec = 0; double currenttime = 0; double lasttime = 0; int addr_family = 0; int use_fec_oti_ext_hdr = 0; double loss_prob = 0; int retval = 0; double tx_percent = 0; s = get_alc_session(*s_id); if(ch_id != NULL) { /* Null-CC and one channel */ ch = s->ch_list[*ch_id]; addr_family = s->addr_family; use_fec_oti_ext_hdr = s->use_fec_oti_ext_hdr; if(toi == FDT_TOI) { /* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FDT + EXT_CENC + EXT_FTI + FEC_PL_ID + UDP + IP */ if(addr_family == PF_INET) { if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 4 + 8 + 20); } else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) || (fec_enc_id == SB_SYS_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 8 + 8 + 20); } } else if(addr_family == PF_INET6) { if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 4 + 8 + 40); } else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) || (fec_enc_id == SB_SYS_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 4 + 16 + 8 + 8 + 40); } } } else { if(addr_family == PF_INET) { if(use_fec_oti_ext_hdr == 1) { /* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */ if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 20); } else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) || (fec_enc_id == SB_SYS_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 20); } } else if(use_fec_oti_ext_hdr == 0) { /* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */ if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 20); } else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) || (fec_enc_id == SB_SYS_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 20); } } } else if(addr_family == PF_INET6) { if(use_fec_oti_ext_hdr == 1) { /* eslen + DEF_LCT_HDR + TSI + TOI + EXT_FTI + FEC_PL_ID + UDP + IP */ if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 4 + 8 + 40); } else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) || (fec_enc_id == SB_SYS_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 16 + 8 + 8 + 40); } } else if(use_fec_oti_ext_hdr == 0) { /* eslen + DEF_LCT_HDR + TSI + TOI + FEC_PL_ID + UDP + IP */ if(((fec_enc_id == COM_NO_C_FEC_ENC_ID) || (fec_enc_id == COM_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 4 + 8 + 40); } else if(((fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) || (fec_enc_id == SB_LB_E_FEC_ENC_ID) || (fec_enc_id == SB_SYS_FEC_ENC_ID))) { packet_length = es_len + (sizeof(def_lct_hdr_t) + 4 + 4 + 8 + 8 + 40); } } } } packetpersec = ((double)(ch->tx_rate * 1000) / (double)(packet_length * 8)); interval = ((double)1 / packetpersec); } if(fec_enc_id == COM_NO_C_FEC_ENC_ID) { tr_block = null_fec_encode_src_block(buf, buf_len, sbn, es_len); } else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) { tr_block = xor_fec_encode_src_block(buf, buf_len, sbn, es_len); } else if(((fec_enc_id == SB_SYS_FEC_ENC_ID) && (fec_inst_id == REED_SOL_FEC_INST_ID))) { tr_block = rs_fec_encode_src_block(buf, buf_len, sbn, es_len, s->def_fec_ratio, max_sb_len); } else { printf("FEC Encoding %i/%i is not supported!\n", fec_enc_id, fec_inst_id); return -1; } if(tr_block == NULL) { return -1; } if(ch_id != NULL) { lasttime = sec(); tb_data_left = es_len * tr_block->n; tr_unit = tr_block->unit_list; for(i = 0; i < tr_block->n; i++) { while(1) { if(s->state == SExiting) { while(1) { free(tr_unit->data); if(tr_unit->esi == (tr_block->n - 1)) { break; } tr_unit++; } free(tr_block->unit_list); free(tr_block); return -2; } currenttime = sec(); if (ch->s->calculate_session_size == false) { while (currenttime < (lasttime + interval)) { if(s->optimize_tx_rate) {#ifdef WIN32 Sleep(0);#else usleep(0);#endif } else {#ifdef WIN32 Sleep(1);#else usleep(1000);#endif } currenttime = sec(); } } loss_prob = 0; if(s->simul_losses) { if(ch->previous_lost == true) { loss_prob = s->loss_ratio2; } else { loss_prob = s->loss_ratio1; } } if(!randomloss(loss_prob)) { retval = send_unit(tr_unit, tr_block, s, ch, toi, toi_len, max_sb_len, es_len, fec_enc_id, fec_inst_id); if(retval < 0) { while(1) { free(tr_unit->data); if(tr_unit->esi == (tr_block->n - 1)) { break; } tr_unit++; } free(tr_block->unit_list); free(tr_block); return -1; } sent += tr_unit->len; add_object_sent_bytes(*s_id, tb_data_left < tr_unit->len ? (unsigned int)tb_data_left : tr_unit->len); tb_data_left -= tb_data_left < tr_unit->len ? tb_data_left : tr_unit->len; if(((toi == FDT_TOI && s->verbosity == 4) || (toi != FDT_TOI && s->verbosity > 1))) {#ifdef WIN32 tx_percent = (double)((double)(100 * ((double)(LONGLONG)get_object_sent_bytes(*s_id)/ (double)(LONGLONG)toi_len))); if(((tx_percent >= (get_object_last_print_tx_percent(*s_id) + 1)) || (tx_percent == 100))) { set_object_last_print_tx_percent(*s_id, tx_percent); printf("%.2f%% of object sent (TOI=%I64u)\n", tx_percent, toi); }#else tx_percent = (double)((double)(100 * ((double)(long long)get_object_sent_bytes(*s_id)/ (double)(long long)toi_len))); if(((tx_percent >= (get_object_last_print_tx_percent(*s_id) + 1)) || (tx_percent == 100))) { set_object_last_print_tx_percent(*s_id, tx_percent); printf("%.2f%% of object sent (TOI=%llu)\n", tx_percent, toi); } #endif fflush(stdout); } ch->previous_lost = false; } else { ch->previous_lost = true; } lasttime += interval; break; } free(tr_unit->data); tr_unit++; } free(tr_block->unit_list); free(tr_block); } else { tr_unit = tr_block->unit_list; for(i = 0; i < tr_block->n; i++) { retval = send_unit(tr_unit, tr_block, s, NULL, toi, toi_len, max_sb_len, es_len, fec_enc_id, fec_inst_id); if(retval == -1) { i--; continue; } else if(retval == -2) { while(1) { free(tr_unit->data); if(tr_unit->esi == (tr_block->n - 1)) { break; } tr_unit++; } free(tr_block->unit_list); free(tr_block); return retval; } free(tr_unit->data); tr_unit++; } free(tr_block->unit_list); free(tr_block); } return sent;}/* * This function sends one unit to tx_queue. * * Params: trans_unit_t *tr_unit: Pointer to transport unit to be sent, * trans_block_t *tr_block: Pointer to transport block that this units belongs, * alc_session_t *s: Pointer to session, * alc_channel_t *ch: Pointer to channel, * unsigned int toi: Transport Object Identifier, * ULONGLONG/unsigned long long toilen: Length of transport object, * unsigned int max_sblen: Maximum-Size Source Block Length, * unsigned short eslen: Encoding Symbol Length, * unsigned char fec_enc_id: FEC Encoding ID, * unsigned short fec_inst_id: FEC Instance ID. * * Return: int: 0 in success, -1 or -2 in error/stopping cases. * */int send_unit(trans_unit_t *tr_unit, trans_block_t *tr_block, alc_session_t *s,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -