OutOfOrderEventDataReconstructor.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 __OUTOFORDEREVENTDATARECONSTRUCTOR_H_3E331BC5510F68__
00042 #define __OUTOFORDEREVENTDATARECONSTRUCTOR_H_3E331BC5510F68__
00043
00044
00045 #include "debug.h"
00046
00047 #include "mw/afp/defrag/detail/VarHeaderLength.h"
00048
00049 #include <string.h>
00050
00051
00052 namespace famouso {
00053 namespace mw {
00054 namespace afp {
00055 namespace defrag {
00056
00057
00067 template <class DCP>
00068 class OutOfOrderEventDataReconstructor {
00069
00070 typedef typename DCP::SizeProp::elen_t elen_t;
00071 typedef typename DCP::SizeProp::flen_t flen_t;
00072 typedef typename DCP::SizeProp::fcount_t fcount_t;
00073
00074 typedef class DCP::DefragStatistics Statistics;
00075 typedef class DCP::Allocator Allocator;
00076 typedef detail::VarHeaderLength<DCP> VHL;
00077 typedef typename VHL::eelen_t eelen_t;
00078
00079 public:
00080
00081 typedef NoFECHeaderSupport<DCP> FECHeaderPolicy;
00082
00083 protected:
00084
00085 uint8_t * event_data;
00086 uint8_t * behind_event_data;
00087 elen_t event_length;
00088
00089 bool event_fragment_count_final;
00090 fcount_t event_fragment_count;
00091
00092 fcount_t arrived_fragment_count;
00093
00094 flen_t no_ext_mtu;
00095
00096
00101 void realloc_event_data(fcount_t new_fragment_count) {
00102 eelen_t old_len = behind_event_data - event_data;
00103 eelen_t new_len = VHL::get_payload(new_fragment_count, no_ext_mtu);
00104
00105 uint8_t * new_data = Allocator::alloc(new_len);
00106 if (!new_data) {
00107 ::logging::log::emit< ::logging::Warning>()
00108 << PROGMEMSTRING("AFP: Out of memory -> drop")
00109 << ::logging::log::endl;
00110 no_ext_mtu = 0;
00111 return;
00112 }
00113
00114 memcpy(new_data + (new_len - old_len), event_data, old_len);
00115 Allocator::free(event_data);
00116
00117 event_data = new_data;
00118 behind_event_data = new_data + new_len;
00119 event_fragment_count = new_fragment_count;
00120 }
00121 public:
00122
00127 OutOfOrderEventDataReconstructor(flen_t no_ext_mtu)
00128 : event_data(0), event_length(0),
00129 event_fragment_count_final(false), event_fragment_count(0),
00130 arrived_fragment_count(0), no_ext_mtu(no_ext_mtu) {
00131 }
00132
00134 ~OutOfOrderEventDataReconstructor() {
00135
00136
00137
00138 if (event_data != reinterpret_cast<uint8_t *>(-1)) {
00139
00140
00141
00142 if (!is_complete())
00143 Statistics::event_incomplete();
00144
00145 Statistics::fragments_currently_expected_sub(event_fragment_count - arrived_fragment_count);
00146 if (event_data)
00147 Allocator::free(event_data);
00148 }
00149 }
00150
00157 void put_fragment(const Headers<DCP> & header, const uint8_t * data, flen_t length) {
00158
00159 FOR_FAMOUSO_ASSERT_ONLY(bool wrong_mtu_or_frag_len = length != no_ext_mtu - VHL::get_basic_header_len(header.fseq) && header.fseq != 0);
00160 FAMOUSO_ASSERT(!wrong_mtu_or_frag_len);
00161 FAMOUSO_ASSERT(!is_complete());
00162
00163 if (no_ext_mtu == 0)
00164 return;
00165 if (header.fec.occurs()) {
00166 ::logging::log::emit< ::logging::Warning>()
00167 << PROGMEMSTRING("AFP: FEC not supported -> drop")
00168 << ::logging::log::endl;
00169 goto set_error;
00170 }
00171
00172 if (header.first_fragment)
00173 event_fragment_count_final = true;
00174
00175 if (!event_data) {
00176
00177 event_fragment_count = header.fseq + (header.first_fragment ? 1 : 2);
00178
00179 eelen_t buffer_length = VHL::get_payload(event_fragment_count, no_ext_mtu);
00180 event_data = Allocator::alloc(buffer_length);
00181 if (!event_data) {
00182 ::logging::log::emit< ::logging::Warning>()
00183 << PROGMEMSTRING("AFP: Out of memory -> drop")
00184 << ::logging::log::endl;
00185 goto set_error;
00186 }
00187 behind_event_data = event_data + buffer_length;
00188
00189 Statistics::fragments_expected(event_fragment_count);
00190 Statistics::fragments_currently_expected_add(event_fragment_count - 1);
00191
00192 } else if (header.fseq >= event_fragment_count) {
00193
00194
00195 fcount_t new_frag_count = header.fseq + 1;
00196 fcount_t additional_frag = new_frag_count - event_fragment_count;
00197
00198 realloc_event_data(new_frag_count);
00199
00200 Statistics::fragments_expected(additional_frag);
00201 Statistics::fragments_currently_expected_add(additional_frag - 1);
00202
00203 } else {
00204
00205 Statistics::fragments_currently_expected_sub(1);
00206 }
00207
00208
00209 memcpy(behind_event_data - VHL::get_payload(header.fseq + 1, no_ext_mtu), data, length);
00210
00211 arrived_fragment_count++;
00212 event_length += length;
00213
00214 Statistics::fragment_used();
00215
00216 if (is_complete())
00217 Statistics::event_complete();
00218
00219 return;
00220
00221 set_error:
00222 no_ext_mtu = 0;
00223 return;
00224 }
00225
00229 bool is_complete() {
00230 return arrived_fragment_count == event_fragment_count && event_fragment_count_final && !error();
00231 }
00232
00237 uint8_t * get_data() {
00238 FAMOUSO_ASSERT(is_complete());
00239 return event_data;
00240 }
00241
00246 elen_t get_length() {
00247 FAMOUSO_ASSERT(is_complete());
00248 return event_length;
00249 }
00250
00254 bool error() {
00255 return no_ext_mtu == 0;
00256 }
00257 };
00258
00259
00260 }
00261 }
00262 }
00263 }
00264
00265
00266 #endif // __OUTOFORDEREVENTDATARECONSTRUCTOR_H_3E331BC5510F68__
00267