/* $Id: mcl_alc_hdr.cpp,v 1.2 2003/10/17 10:14:50 roca Exp $ */ /* * Copyright (c) 1999-2003 INRIA - Universite Paris 6 - All rights reserved * (main author: Vincent Roca - vincent.roca@inrialpes.fr) * * 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 "mcl_includes.h" static int alc_hdr_add_FPI_he (mclcb_t *mclcb, char *ptr, int hlen, hdr_infos_t *hdr_infos); static int alc_hdr_parse_FPI_he (mclcb_t *mclcb, char *ptr, int hlen, int plen, hdr_infos_t *hdr_infos); /****** sending side **********************************************************/ /* * Initializes the ALC header * Assumes that the memory block has been allocated by the caller * who MUST ensure that it will be large enough to hold all the * possible fields! * Returns the size of the ALC header (bytes), -1 if error. */ int alc_hdr_create (mclcb_t *mclcb, fixed_lct_hdr_t *lct_hdr, hdr_infos_t *hdr_infos) { int hlen; /* length of the fixed+variable_len headers */ TRACELVL(5, (mcl_stdout, "-> alc_hdr_create:\n")) if ((hlen = lct_hdr_create(mclcb, lct_hdr, hdr_infos)) < 0) { goto bad; } if (hdr_infos->FPI_present) { hlen = alc_hdr_add_FPI_he(mclcb, (char*)lct_hdr, hlen, hdr_infos); } TRACELVL(5, (mcl_stdout, "<- alc_hdr_create:\n")) return hlen; bad: TRACELVL(5, (mcl_stdout, "<- alc_hdr_create: ERROR\n")) return -1; } /* * Add a FPI extension, using the provided hdr_infos. * * with FEC_ENCODING_ID_SMALL_LARGE_EXP_FEC and FEC_ENCODING_ID_LDPC_FEC: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | source block idf | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |F| encoding symbol idf | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * the F flag, if set, indicates that it is a FEC symbol * * with FEC_ENCODING_ID_NO_FEC: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | source block idf | encoding symbol idf | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Returns the new size of the header (bytes) with this * header extension, or -1 if error. */ static int alc_hdr_add_FPI_he (mclcb_t *mclcb, char *ptr, /* write at ptr+hlen then update hlen */ int hlen, hdr_infos_t *hdr_infos) { u_int32_t word = 0; TRACELVL(5, (mcl_stdout, "-> alc_hdr_add_FPI_he:\n")) ASSERT(hdr_infos); if ((hdr_infos->fec_encoding_id == FEC_ENCODING_ID_SMALL_LARGE_EXP_FEC) || (hdr_infos->fec_encoding_id == FEC_ENCODING_ID_LDPC_FEC)) { /* 64 bit of encoding ID */ *(u_int32_t*)(ptr + hlen) = htonl(hdr_infos->idf_block); hlen += 4; word = ((hdr_infos->is_fec ? 1 : 0) << 31) | (hdr_infos->idf_du & 0x7FFFFFFF); *(u_int32_t*)(ptr + hlen) = htonl(word); hlen += 4; } else if ((hdr_infos->fec_encoding_id == FEC_ENCODING_ID_NO_FEC)) { /* 32 bit of encoding ID */ word = (hdr_infos->idf_block << 16) | (hdr_infos->idf_du & 0x0000FFFF); *(u_int32_t*)(ptr + hlen) = htonl(word); hlen += 4; } TRACELVL(5, (mcl_stdout, "<- alc_hdr_add_FPI_he: hlen=%d\n", hlen)) return hlen; } /****** receiving side ********************************************************/ /* * Parses the ALC header of the received packet * Returns the size of the ALC header (bytes), -1 if error. */ int alc_hdr_parse (mclcb_t *mclcb, fixed_lct_hdr_t *lct_hdr, hdr_infos_t *hdr_infos, int plen) /* packet len (data+rlc+alc headers) */ { int hlen; TRACELVL(5, (mcl_stdout, "-> alc_hdr_parse:\n")) if ((hlen = lct_hdr_parse(mclcb, lct_hdr, hdr_infos)) < 0) { goto bad_hdr; } if (plen > hlen) { if ((hlen = alc_hdr_parse_FPI_he(mclcb, (char*)lct_hdr, hlen, plen, hdr_infos)) < 0) { goto bad_hdr; } } TRACELVL(5, (mcl_stdout, "<- alc_hdr_parse: \n")) return hlen; bad_hdr: PRINT_ERR((mcl_stderr, "alc_hdr_parse: ERROR, bad header, dropped\n")) TRACELVL(5, (mcl_stdout, "<- alc_hdr_parse: error\n")) return -1; } static int alc_hdr_parse_FPI_he (mclcb_t *mclcb, char *ptr, /* read at ptr+hlen */ int hlen, int plen, hdr_infos_t *hdr_infos) { u_int32_t word; TRACELVL(5, (mcl_stdout, "-> alc_hdr_parse_FPI_he:\n")) if ((hdr_infos->fec_encoding_id == FEC_ENCODING_ID_SMALL_LARGE_EXP_FEC) || (hdr_infos->fec_encoding_id == FEC_ENCODING_ID_LDPC_FEC)) { /* 64 bit of encoding ID */ if (plen < hlen + 8) { TRACELVL(5, (mcl_stdout, " alc_hdr_parse_FPI_he: ERROR, too short (expected %d, actual len %d)\n", hlen + 8, plen)) return -1; } hdr_infos->idf_block = ntohl(*(int*)(ptr + hlen)); hlen += 4; word = ntohl(*(int*)(ptr + hlen)); hdr_infos->is_fec = (word & 0x80000000) ? true : false; hdr_infos->idf_du = (word & 0x7FFFFFFF); hlen += 4; } else if ((hdr_infos->fec_encoding_id == FEC_ENCODING_ID_NO_FEC)) { /* 32 bit of encoding ID */ if (plen < hlen + 4) { TRACELVL(5, (mcl_stdout, " alc_hdr_parse_FPI_he: ERROR, too short (expected %d, actual len %d)\n", hlen + 4, plen)) return -1; } word = ntohl(*(int*)(ptr + hlen)); hdr_infos->idf_block = (word >> 16); hdr_infos->is_fec = false; /* no FEC here */ hdr_infos->idf_du = (word & 0x0000FFFF); hlen += 4; } hdr_infos->FPI_present = true; TRACELVL(5, (mcl_stdout, "<- alc_hdr_parse_FPI_he: hlen=%d\n", hlen)) return hlen; }