📄 alc_rx.c
字号:
/* $Author: peltotas $ $Date: 2006/03/14 12:01:00 $ $Revision: 1.86 $ *//* * 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 analyze_packet(char *data, int len, alc_channel_t *ch);int recv_packet(alc_session_t *s);/* * This function receives packets from all channels in one session in thread. * * Params: void *s: Pointer to session * * Return: void * */void* rx_thread(void *s) { alc_session_t *session; int retval = 0; srand((unsigned)time(NULL)); session = (alc_session_t *)s; while(session->state == SActive) { if(session->nb_channel != 0) { retval = recv_packet(session); }/*#ifdef WIN32 Sleep(1);#else usleep(1000);#endif*/ }#ifdef WIN32 _endthread();#else pthread_exit(0);#endif return NULL;}/* * This function receives unit(s) from session's channels. * * Params: alc_session_t *s: Pointer to session * * Return: int: Number of correct packets received from ALC session * */int recv_packet(alc_session_t *s) { char recvbuf[MAX_PACKET_LENGTH]; int recvlen; int nb; int i; int retval; int max_fd = 0; int recv_pkts = 0; fd_set rfds; alc_channel_t *ch; struct timeval tv; struct sockaddr_storage from; char hostname[100]; double loss_prob;#ifdef WIN32 int fromlen;#else socklen_t fromlen;#endif if(s->addr_family == PF_INET) { fromlen = sizeof(struct sockaddr_in); } else if(s->addr_family == PF_INET6) { fromlen = sizeof(struct sockaddr_in6); } memset(recvbuf, 0, MAX_PACKET_LENGTH); FD_ZERO(&rfds); tv.tv_sec = 1; tv.tv_usec = 0; for(i = 0; i < s->max_channel; i++) { ch = s->ch_list[i]; if(ch != NULL) { FD_SET(ch->rx_sock, &rfds); max_fd = max((int)ch->rx_sock, max_fd); } } nb = select((max_fd + 1), &rfds, NULL, NULL, &tv); if(nb <= 0) { return 0; } for(i = 0; i < s->max_channel; i++) { ch = s->ch_list[i]; if(ch != NULL) { memset((void *)&from, 0, sizeof(from)); if(FD_ISSET(ch->rx_sock, &rfds)) { recvlen = recvfrom(ch->rx_sock, recvbuf, MAX_PACKET_LENGTH, 0, (struct sockaddr*)&from, &fromlen); if(recvlen < 0) { if(s->state == SExiting) { /*printf("recv_packet() SExiting\n"); fflush(stdout);*/ return -2; } else if(s->state == SClosed) { /*printf("recv_packet() SClosed\n"); fflush(stdout);*/ return 0; } else { #ifdef WIN32 printf("recvfrom failed: %d\n", WSAGetLastError()); fflush(stdout); #else printf("recvfrom failed: %d\n", h_errno); #endif return -1; } } loss_prob = 0; if(ch->s->simul_losses) { if(ch->previous_lost == true) { loss_prob = ch->s->loss_ratio2; } else { loss_prob = ch->s->loss_ratio1; } } if(!randomloss(loss_prob)) { getnameinfo((struct sockaddr*)&from, fromlen, hostname, sizeof(hostname), NULL, 0, NI_NUMERICHOST); if(strcmp(s->src_addr, "") != 0) { if(strcmp(hostname, s->src_addr) != 0) { printf("Packet to wrong session: wrong source: %s\n", hostname); fflush(stdout); continue; } } retval = analyze_packet(recvbuf, recvlen, ch); if(strcmp(s->src_addr, "") == 0) { if(s->verbosity > 0) { printf("Locked to source: %s\n", hostname); fflush(stdout); } memcpy(s->src_addr, hostname, strlen(hostname)); } if(ch->s->cc_id == RLC) { if(((ch->s->rlc->drop_highest_layer) && (ch->s->nb_channel != 1))) { ch->s->rlc->drop_highest_layer = false; close_alc_channel(ch->s->ch_list[ch->s->nb_channel - 1], ch->s); } } if(retval == HDR_ERROR) { continue; } else if(retval == DUP_PACKET) { continue; } else if(retval == MEM_ERROR) { return -1; } recv_pkts++; ch->previous_lost = false; } else { ch->previous_lost = true; } } } } return recv_pkts;}/* * This function parses and analyzes alc packet. * * Params: char *data: Pointer to packet's data, * int len: Length of packet's data, * alc_channel_t *ch: Pointer to channel * * Return: int: Status of packet (OK, EMPTY_PACKET, HDR_ERROR, MEM_ERROR, DUP_PACKET) * */int analyze_packet(char *data, int len, alc_channel_t *ch) { def_lct_hdr_t *def_lct_hdr = NULL; int hdrlen = 0; /* length of whole header */ int retval = 0; #ifdef WIN32 ULONGLONG tsi = 0; ULONGLONG toi = 0; ULONGLONG toi_len = 0;#else unsigned long long tsi = 0; unsigned long long toi = 0; unsigned long long toi_len = 0;#endif unsigned int sbn = 0; unsigned int esi = 0; unsigned short es_len = 0; unsigned short sb_len = 0; unsigned int max_sb_len = 0; unsigned short max_nb_of_es = 0; short fec_enc_id = 0; int fec_inst_id = 0; int fdt_instance_id = 0; unsigned short flute_version = 0; unsigned char content_enc_algo = 0; unsigned short reserved = 0; unsigned int word = 0; #ifdef WIN32 ULONGLONG ull = 0;#else unsigned long long ull = 0;#endif trans_obj_t *trans_obj = NULL; trans_block_t *trans_block = NULL; trans_unit_t *trans_unit = NULL; trans_unit_t *tu = NULL; trans_unit_t *next_tu = NULL; wanted_obj_t *wanted_obj = NULL; int het = 0; int hel = 0; int exthdrlen = 0; char *buf = NULL; #ifdef WIN32 ULONGLONG block_len = 0; ULONGLONG pos = 0;#else unsigned long long block_len = 0; unsigned long long pos = 0;#endif char filename[MAX_PATH]; double rx_percent = 0; unsigned int i = 0; if(len < (int)(sizeof(def_lct_hdr_t))) { printf("analyze_packet: packet too short %d\n", len); fflush(stdout); return HDR_ERROR; } def_lct_hdr = (def_lct_hdr_t*)data; *(unsigned short*)def_lct_hdr = ntohs(*(unsigned short*)def_lct_hdr); hdrlen += (int)(sizeof(def_lct_hdr_t)); if(def_lct_hdr->version != ALC_VERSION) { printf("ALC version: %i not supported!\n", def_lct_hdr->version); fflush(stdout); return HDR_ERROR; } if(def_lct_hdr->reserved != 0) { printf("Reserved field not zero!\n"); fflush(stdout); return HDR_ERROR; } if(def_lct_hdr->flag_t != 0) { printf("Sender Current Time not supported!\n"); fflush(stdout); return HDR_ERROR; } if(def_lct_hdr->flag_r != 0) { printf("Expected Residual Time not supported!\n"); fflush(stdout); return HDR_ERROR; } if(def_lct_hdr->flag_b == 1) { /**** TODO ****/ } if(def_lct_hdr->flag_c != 0) { printf("Only 32 bits CCI-field supported!\n"); fflush(stdout); return HDR_ERROR; } else { if(def_lct_hdr->cci != 0) { if(ch->s->cc_id == RLC) { retval = mad_rlc_analyze_cci(ch->s, (rlc_hdr_t*)(data + 4)); if(retval < 0) { return HDR_ERROR; } } } } if(def_lct_hdr->flag_h == 1) { if(def_lct_hdr->flag_s == 0) { /* TSI 16 bits */ word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; tsi = (word & 0xFFFF0000) >> 16; if(tsi != ch->s->tsi) {#ifdef WIN32 printf("Packet to wrong session: wrong TSI: %I64u\n", tsi);#else printf("Packet to wrong session: wrong TSI: %llu\n", tsi);#endif fflush(stdout); return HDR_ERROR; } } else if(def_lct_hdr->flag_s == 1) { /* TSI 48 bits */ ull = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); tsi = ull << 16; hdrlen += 4; word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; tsi += (word & 0xFFFF0000) >> 16; if(tsi != ch->s->tsi) {#ifdef WIN32 printf("Packet to wrong session: wrong TSI: %I64u\n", tsi);#else printf("Packet to wrong session: wrong TSI: %llu\n", tsi);#endif fflush(stdout); return HDR_ERROR; } } if(def_lct_hdr->flag_a == 1) { ch->s->state = STxStopped; } if(def_lct_hdr->flag_o == 0) { /* TOI 16 bits */ toi = (word & 0x0000FFFF); } else if(def_lct_hdr->flag_o == 1) { /* TOI 48 bits */ ull = (word & 0x0000FFFF); toi = ull << 32; toi += ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; } else { printf("Only 16, 32, 48 or 64 bits TOI-field supported!\n"); fflush(stdout); return HDR_ERROR; } /*else if(def_lct_hdr->flag_o == 2) { } else if(def_lct_hdr->flag_o == 3) { }*/ } else { if(def_lct_hdr->flag_s == 1) { /* TSI 32 bits */ tsi = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; if(tsi != ch->s->tsi) {#ifdef WIN32 printf("Packet to wrong session: wrong TSI: %I64u\n", tsi);#else printf("Packet to wrong session: wrong TSI: %llu\n", tsi);#endif fflush(stdout); return HDR_ERROR; } } else { printf("Transport Session Identifier not present!\n"); fflush(stdout); return HDR_ERROR; } if(def_lct_hdr->flag_a == 1) { ch->s->state = STxStopped; } if(def_lct_hdr->flag_o == 0) { /* TOI 0 bits */ if(def_lct_hdr->flag_a != 1) { printf("Transport Object Identifier not present!\n"); fflush(stdout); return HDR_ERROR; } else { return EMPTY_PACKET; } } else if(def_lct_hdr->flag_o == 1) { /* TOI 32 bits */ toi = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; } else if(def_lct_hdr->flag_o == 2) { /* TOI 64 bits */ ull = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); toi = ull << 32; hdrlen += 4; toi += ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; } else { printf("Only 16, 32, 48 or 64 bits TOI-field supported!\n"); fflush(stdout); return HDR_ERROR; } /*else if(def_lct_hdr->flag_o == 3) { }*/ } if(!toi == FDT_TOI) { wanted_obj = get_wanted_object(ch->s, toi); if(wanted_obj == NULL) { /*printf("Packet to not wanted toi: %i\n", toi); fflush(stdout);*/ return HDR_ERROR; } es_len = wanted_obj->es_len; max_sb_len = wanted_obj->max_sb_len; max_nb_of_es = wanted_obj->max_nb_of_es; fec_enc_id = wanted_obj->fec_enc_id; fec_inst_id = wanted_obj->fec_inst_id; toi_len = wanted_obj->toi_len; /* #ifdef USE_ZLIB */ content_enc_algo = wanted_obj->content_enc_algo; /* #endif */ } fec_enc_id = def_lct_hdr->codepoint; if(fec_enc_id == COM_NO_C_FEC_ENC_ID) { } else if(fec_enc_id == SB_SYS_FEC_ENC_ID) { } else if(fec_enc_id == SIMPLE_XOR_FEC_ENC_ID) { } else { printf("FEC Encoding ID: %i is not supported!\n", fec_enc_id); fflush(stdout); return HDR_ERROR; } if(def_lct_hdr->hdr_len > (hdrlen >> 2)) { /* LCT header extensions(EXT_FDT, EXT_CENC, EXT_FTI, EXT_AUTH, EXT_NOP) go through all possible EH */ exthdrlen = def_lct_hdr->hdr_len - (hdrlen >> 2); while(exthdrlen > 0) { word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; exthdrlen--; het = (word & 0xFF000000) >> 24; if(het < 128) { hel = (word & 0x00FF0000) >> 16; } switch(het) { case EXT_FDT: flute_version = (word & 0x00F00000) >> 20; fdt_instance_id = (word & 0x000FFFFF); if(flute_version != FLUTE_VERSION) { printf("FLUTE version: %i is not supported\n", flute_version); return HDR_ERROR; } break; case EXT_CENC: content_enc_algo = (word & 0x00FF0000) >> 16; reserved = (word & 0x0000FFFF); if(reserved != 0) { printf("Bad CENC header extension!\n"); return HDR_ERROR; } #ifdef USE_ZLIB if((content_enc_algo != 0) && (content_enc_algo != ZLIB)) { printf("Only NULL or ZLIB content encoding supported with FDT Instance!\n"); return HDR_ERROR; }#else if(content_enc_algo != 0) { printf("Only NULL content encoding supported with FDT Instance!\n"); return HDR_ERROR; }#endif break; case EXT_FTI: if(hel != 4) { printf("Bad FTI header extension, length: %i\n", hel); return HDR_ERROR; } toi_len = ((word & 0x0000FFFF) << 16); toi_len += ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; exthdrlen--; word = ntohl(*(unsigned int*)((char*)def_lct_hdr + hdrlen)); hdrlen += 4; exthdrlen--; fec_inst_id = ((word & 0xFFFF0000) >> 16); if(fec_enc_id == SB_SYS_FEC_ENC_ID) { if(fec_inst_id != REED_SOL_FEC_INST_ID) { printf("FEC Encoding %i/%i is not supported!\n", fec_enc_id, fec_inst_id);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -