FECFragmenter.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifndef __FECFRAGMENTER_H_248EC79C4F9347__
00043 #define __FECFRAGMENTER_H_248EC79C4F9347__
00044
00045
00046 #include "debug.h"
00047
00048 #include "mw/afp/frag/NoFECFragmenter.h"
00049 #include "mw/afp/frag/UseFEC.h"
00050 #include "mw/afp/shared/div_round_up.h"
00051
00052
00053 #include <string.h>
00054
00055
00056 namespace famouso {
00057 namespace mw {
00058 namespace afp {
00059 namespace frag {
00060
00061
00069 template < class FCP >
00070 class FECFragmenter : public NoFECFragmenter<FCP> {
00071
00072 typedef NoFECFragmenter<FCP> Base;
00073
00074 typedef typename FCP::SizeProp::elen_t elen_t;
00075 typedef typename FCP::SizeProp::flen_t flen_t;
00076 typedef typename FCP::SizeProp::fcount_t fcount_t;
00077
00078 typedef class FCP::OverflowErrorChecking OverflowErrorCheck;
00079 typedef UseFEC<FCP> FEC;
00080
00081 protected:
00082
00084 FEC fec;
00085
00087 bool redundancy;
00088
00089 public:
00090
00092 enum { min_header_length = Base::min_header_length + FEC::header_length };
00093
00095 enum { extension_header_length = Base::extension_header_length + FEC::header_length };
00096
00103 void init(const uint8_t * event_data, elen_t event_length, flen_t mtu) {
00104
00105
00106 if (mtu <= min_header_length + 1) {
00107 Base::err = true;
00108 ::logging::log::emit< ::logging::Error>()
00109 << PROGMEMSTRING("AFP: MTU too small for selected features.")
00110 << ::logging::log::endl;
00111 return;
00112 }
00113
00114 Base::err = false;
00115 OverflowErrorCheck overflow_err;
00116
00117
00118
00119 flen_t header_length = min_header_length;
00120 flen_t payload_length = mtu - header_length;
00121
00122
00123 if (payload_length & 1)
00124 payload_length--;
00125
00126 elen_t k = shared::div_round_up(event_length, (elen_t)payload_length);
00127 overflow_err.check_equal(k, (fcount_t)k);
00128
00129 fcount_t frag_count = FEC::k2n(k);
00130 overflow_err.check_smaller_or_equal(k, frag_count);
00131
00132 fcount_t max_fragments = 32;
00133
00134 while (frag_count > max_fragments &&
00135 !overflow_err.error()) {
00136 header_length++;
00137 payload_length = mtu - header_length;
00138 if (payload_length & 1)
00139 payload_length--;
00140
00141 if (payload_length == 0)
00142 break;
00143
00144 k = shared::div_round_up(event_length, (elen_t)payload_length);
00145 overflow_err.check_equal(k, (fcount_t)k);
00146
00147 frag_count = FEC::k2n(k);
00148 overflow_err.check_smaller_or_equal(k, frag_count);
00149
00150 overflow_err.check_smaller(max_fragments, max_fragments << 7);
00151 max_fragments <<= 7;
00152 }
00153
00154 if (frag_count == k) {
00155
00156 redundancy = false;
00157 Base::init(event_data, event_length, mtu);
00158 return;
00159 } else {
00160 redundancy = true;
00161 }
00162
00163 ::logging::log::emit< ::logging::Info>()
00164 << PROGMEMSTRING("AFP: Fragmenter: ")
00165 << ::logging::log::dec << static_cast<uint64_t>(event_length)
00166 << PROGMEMSTRING(" bytes data -> ")
00167 << static_cast<uint64_t>(payload_length)
00168 << PROGMEMSTRING(" bytes payload in ")
00169 << static_cast<uint64_t>(frag_count)
00170 << PROGMEMSTRING(" fragments")
00171 << ::logging::log::endl;
00172
00173 if (payload_length == 0 || overflow_err.error()) {
00174 Base::err = true;
00175 ::logging::log::emit< ::logging::Error>()
00176 << PROGMEMSTRING("AFP: Event of size ")
00177 << ::logging::log::dec << static_cast<uint64_t>(event_length)
00178 << PROGMEMSTRING(" could not be fragmented with this configuration (too large).")
00179 << ::logging::log::endl;
00180 return;
00181 }
00182
00183 FAMOUSO_ASSERT(frag_count > 0);
00184 Base::remaining_fragments = frag_count;
00185 Base::next_header_shorten_fseq = get_next_header_shorten_fseq(frag_count-1);
00186
00187 Base::payload_length = payload_length;
00188 Base::first_fragment = true;
00189 Base::basic_header_length = header_length - extension_header_length;
00190 Base::remaining_data = event_data;
00191 Base::remaining_length = event_length;
00192
00193 fec.init(event_length, payload_length, k);
00194 }
00195
00196 public:
00197
00203 flen_t get_fragment(uint8_t * fragment_data) {
00204 if (!redundancy)
00205 return Base::get_fragment(fragment_data);
00206
00207 if (!Base::remaining_fragments)
00208 return 0;
00209
00210 Base::remaining_fragments--;
00211
00212
00213 if (Base::remaining_fragments == Base::next_header_shorten_fseq) {
00214 Base::basic_header_length--;
00215 Base::next_header_shorten_fseq = Base::get_next_header_shorten_fseq(Base::remaining_fragments);
00216 FAMOUSO_ASSERT(Base::basic_header_length > 0);
00217 }
00218
00219
00220 flen_t fragment_length = Base::get_header(fragment_data, true);
00221 fragment_data += fragment_length;
00222
00223
00224 fec.get_header(fragment_data, false);
00225 fragment_length += FEC::header_length;
00226 fragment_data += FEC::header_length;
00227
00228
00229 if (Base::remaining_length == 0) {
00230
00231
00232 fec.get_red_fragment(fragment_data);
00233 fragment_length += Base::payload_length;
00234
00235 } else if (Base::remaining_length >= Base::payload_length) {
00236
00237
00238 memcpy(fragment_data, Base::remaining_data, Base::payload_length);
00239 fec.put_nonred_fragment(Base::remaining_data);
00240 fragment_length += Base::payload_length;
00241
00242 Base::remaining_length -= Base::payload_length;
00243 Base::remaining_data += Base::payload_length;
00244
00245 } else {
00246
00247
00248 memcpy(fragment_data, Base::remaining_data, Base::remaining_length);
00249 fec.put_smaller_nonred_fragment(Base::remaining_data, Base::remaining_length);
00250 fragment_length += Base::remaining_length;
00251
00252 Base::remaining_length = 0;
00253 }
00254
00255 return fragment_length;
00256 }
00257
00258 };
00259
00260
00261 }
00262 }
00263 }
00264 }
00265
00266
00267
00268 #endif // __FECFRAGMENTER_H_248EC79C4F9347__
00269