FECEventDataReconstructor.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 #ifndef __FECEVENTDATARECONSTRUCTOR_H_3E331BC5510F68__
00042 #define __FECEVENTDATARECONSTRUCTOR_H_3E331BC5510F68__
00043
00044
00045 #if !defined(__AVR__)
00046
00047
00048 #include "debug.h"
00049
00050 #include "mw/afp/defrag/OutOfOrderEventDataReconstructor.h"
00051 #include "mw/afp/defrag/detail/VarHeaderLength.h"
00052 #include "mw/afp/shared/expandrange_cast.h"
00053 #include "mw/afp/shared/div_round_up.h"
00054
00055 #include <string.h>
00056
00057
00058 namespace famouso {
00059 namespace mw {
00060 namespace afp {
00061 namespace defrag {
00062
00063
00064 namespace vandermonde_fec {
00065 extern "C" {
00066
00067 #include "fec.h"
00068 }
00069 }
00070
00071
00083 template <class DCP>
00084 class FECEventDataReconstructor : public OutOfOrderEventDataReconstructor<DCP> {
00085
00086 typedef OutOfOrderEventDataReconstructor<DCP> Base;
00087
00088 typedef typename DCP::SizeProp::elen_t elen_t;
00089 typedef typename DCP::SizeProp::flen_t flen_t;
00090 typedef typename DCP::SizeProp::fcount_t fcount_t;
00091
00092 typedef class DCP::DefragStatistics Statistics;
00093 typedef class DCP::Allocator Allocator;
00094 typedef detail::VarHeaderLength<DCP> VHL;
00095
00096 public:
00097
00098 typedef FECHeaderSupport<DCP> FECHeaderPolicy;
00099
00100 private:
00101
00102 uint8_t ** fragments_data;
00103 int * fragments_order;
00104
00105
00106 fcount_t k;
00107
00108 void * fec_code;
00109
00110 flen_t payload_length;
00111
00113 static fcount_t get_redundancy_fragment_count(fcount_t k, uint8_t redundancy) {
00114 return shared::div_round_up(shared::expandrange_cast(k) * redundancy,
00115 shared::expandrange_cast((fcount_t)100));
00116 }
00117
00118 public:
00119
00124 FECEventDataReconstructor(flen_t no_ext_mtu)
00125 : Base(no_ext_mtu), fragments_data(0), fragments_order(0), k(1), fec_code(0), payload_length(0) {
00126 }
00127
00129 ~FECEventDataReconstructor() {
00130
00131
00132
00133 if (!is_complete())
00134 Statistics::event_incomplete();
00135
00136 Statistics::fragments_currently_expected_sub(Base::event_fragment_count - Base::arrived_fragment_count);
00137
00138 if (fec_code)
00139 vandermonde_fec::fec_free(fec_code);
00140
00141 if (fragments_data) {
00142 for (fcount_t i = 0; i < k; i++)
00143 if (fragments_data[i])
00144 Allocator::free(fragments_data[i]);
00145 Allocator::free_array(fragments_data);
00146 }
00147
00148 if (fragments_order)
00149 Allocator::free_array(fragments_order);
00150
00151 if (Base::event_data)
00152 Allocator::free(Base::event_data);
00153
00154
00155
00156
00157 Base::event_data = reinterpret_cast<uint8_t *>(-1);
00158
00159
00160 }
00161
00168 void put_fragment(const Headers<DCP> & header, const uint8_t * data, flen_t length) {
00169 FAMOUSO_ASSERT(!is_complete());
00170
00171 if (Base::error())
00172 return;
00173
00174 if (!header.fec.occurs()) {
00175 Base::put_fragment(header, data, length);
00176 k = 0;
00177 return;
00178 } else if (k == 0) {
00179 goto set_error;
00180 }
00181
00182 if (!fragments_data) {
00183
00184 k = header.fec.get_k();
00185 Base::event_fragment_count = k + get_redundancy_fragment_count(k, header.fec.get_red());
00186
00187 payload_length = Base::no_ext_mtu - VHL::get_basic_header_len(Base::event_fragment_count - 1);
00188
00189 if (payload_length & 1)
00190 payload_length--;
00191
00192 Base::event_length = (k - 1) * payload_length + header.fec.get_len_rest();
00193
00194 Statistics::fragments_expected(Base::event_fragment_count);
00195 Statistics::fragments_currently_expected_add(Base::event_fragment_count);
00196
00197 fragments_data = Allocator::template alloc_array< uint8_t* >(k);
00198 fragments_order = Allocator::template alloc_array<int>(k);
00199
00200 if (Base::event_fragment_count > 0xffff) {
00201 ::logging::log::emit< ::logging::Warning>()
00202 << PROGMEMSTRING("AFP: invalid FEC parameter (too many fragmens) -> drop")
00203 << ::logging::log::endl;
00204 goto set_error;
00205 }
00206
00207 if (!fragments_data || !fragments_order) {
00208 ::logging::log::emit< ::logging::Warning>()
00209 << PROGMEMSTRING("AFP: Out of memory -> drop")
00210 << ::logging::log::endl;
00211 goto set_error;
00212 }
00213
00214 memset(fragments_data, 0, k * sizeof(uint8_t *));
00215
00216 ::logging::log::emit< ::logging::Info>()
00217 << PROGMEMSTRING("AFP: FEC: payload length ")
00218 << ::logging::log::dec
00219 << (unsigned int)payload_length
00220 << PROGMEMSTRING(", k ")
00221 << (unsigned int)k
00222 << PROGMEMSTRING(", n ")
00223 << (unsigned int)Base::event_fragment_count
00224 << ::logging::log::endl;
00225 }
00226
00227 FAMOUSO_ASSERT(header.fseq < Base::event_fragment_count);
00228
00229
00230
00231 {
00232 FOR_FAMOUSO_ASSERT_ONLY(bool wrong_mtu_or_frag_len = length != payload_length && header.fseq != Base::event_fragment_count - k);
00233 FAMOUSO_ASSERT(!wrong_mtu_or_frag_len);
00234 }
00235
00236
00237 fragments_data[Base::arrived_fragment_count] = Allocator::alloc(payload_length);
00238 if (!fragments_data[Base::arrived_fragment_count]) {
00239
00240 ::logging::log::emit< ::logging::Warning>()
00241 << PROGMEMSTRING("AFP: Out of memory -> drop")
00242 << ::logging::log::endl;
00243 return;
00244 }
00245
00246 memcpy(fragments_data[Base::arrived_fragment_count], data, length);
00247 if (payload_length > length)
00248 memset(fragments_data[Base::arrived_fragment_count] + length, 0, payload_length - length);
00249
00250 fragments_order[Base::arrived_fragment_count] = Base::event_fragment_count - header.fseq - 1;
00251
00252 Base::arrived_fragment_count++;
00253
00254 Statistics::fragments_currently_expected_sub(1);
00255 Statistics::fragment_used();
00256
00257 if (is_complete())
00258 Statistics::event_complete();
00259
00260 return;
00261
00262 set_error:
00263 Base::no_ext_mtu = 0;
00264 return;
00265 }
00266
00267
00271 bool is_complete() {
00272
00273 if (k == 0)
00274 return Base::is_complete();
00275
00276
00277 return Base::arrived_fragment_count >= k && !Base::error();
00278 }
00279
00284 uint8_t * get_data() {
00285
00286 if (k == 0)
00287 return Base::get_data();
00288
00289 FAMOUSO_ASSERT(is_complete());
00290
00291 if (!Base::event_data) {
00292 fec_code = vandermonde_fec::fec_new(k, Base::event_fragment_count);
00293
00294 Base::event_data = Allocator::alloc(Base::event_length);
00295 if (!fec_code || !Base::event_data) {
00296 ::logging::log::emit< ::logging::Warning>()
00297 << PROGMEMSTRING("AFP: Out of memory -> drop")
00298 << ::logging::log::endl;
00299 goto set_error;
00300 }
00301
00302
00303 int err = vandermonde_fec::fec_decode(fec_code,
00304 reinterpret_cast<void **>(
00305 const_cast<uint8_t **>(fragments_data)
00306 ),
00307 fragments_order,
00308 payload_length);
00309 if (err != 0) {
00310 ::logging::log::emit< ::logging::Warning>()
00311 << PROGMEMSTRING("AFP: FEC decode error -> drop")
00312 << ::logging::log::endl;
00313 goto set_error;
00314 }
00315
00316
00317 uint8_t * p = Base::event_data;
00318 fcount_t km1 = k - 1;
00319 for (fcount_t i = 0; i < km1; i++, p += payload_length)
00320 memcpy(p, fragments_data[i], payload_length);
00321 memcpy(p, fragments_data[km1], Base::event_length - (km1 * payload_length));
00322 }
00323
00324 return Base::event_data;
00325
00326 set_error:
00327 Base::no_ext_mtu = 0;
00328 return 0;
00329 }
00330
00335 elen_t get_length() {
00336 FAMOUSO_ASSERT(is_complete());
00337 return Base::event_length;
00338 }
00339 };
00340
00341
00342 }
00343 }
00344 }
00345 }
00346
00347
00348 #else
00349
00350
00351 #include "assert/staticerror.h"
00352
00353 namespace famouso {
00354 namespace mw {
00355 namespace afp {
00356 namespace defrag {
00357 template <class DCP>
00358 class FECEventDataReconstructor {
00359 FAMOUSO_STATIC_ASSERT_ERROR(false, FEC_not_supported_on_AVR, ());
00360 };
00361 }
00362 }
00363 }
00364 }
00365
00366 #endif
00367
00368
00369 #endif // __FECEVENTDATARECONSTRUCTOR_H_3E331BC5510F68__
00370