00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_FRAME_FILTER_TIME_ADJUSTER_HXX_
00023 # define WIFI_FRAME_FILTER_TIME_ADJUSTER_HXX_
00024
00025 # include "time_adjuster.hh"
00026
00027 # include <boost/shared_ptr.hpp>
00028 # include <boost/shared_array.hpp>
00029
00030 # include <wipal/phy/prism_header.hh>
00031 # include <wipal/wifi/frame/filter/microseconds_stamper.hh>
00032 # include <wipal/wifi/frame/filter/linear_regression_synchronizer.hh>
00033
00034 namespace wifi
00035 {
00036 namespace frame
00037 {
00038 namespace filter
00039 {
00040
00041 namespace internals
00042 {
00043
00044 template <class I1, class I2, class HT, class B1, class B2>
00045 time_adjuster_iterator<I1, I2, HT, B1, B2>::
00046 time_adjuster_iterator(const iterable_type& i, bool end):
00047 super_type (),
00048 iterable_ (&i),
00049 next1_ (end ? i.last1_ : i.first1_),
00050 next2_ (end ? i.last2_ : i.first2_)
00051 {
00052 if (not end)
00053 increment();
00054 }
00055
00056 template <class I1, class I2, class HT, class B1, class B2>
00057 bool
00058 time_adjuster_iterator<I1, I2, HT, B1, B2>::
00059 equal(const time_adjuster_iterator& rhs) const
00060 {
00061 if (not rhs.value())
00062 return not this->value();
00063 return next1_ == rhs.next1_;
00064 }
00065
00066 template <class I1, class I2, class HT, class B1, class B2>
00067 void
00068 time_adjuster_iterator<I1, I2, HT, B1, B2>::increment()
00069 {
00070 using tool::endian::endianness;
00071
00072 typedef tool::microseconds microseconds;
00073 typedef typename time_converter<>::time_values time_values;
00074 typedef pcapxx::pkthdr pkthdr;
00075 typedef boost::shared_ptr<pkthdr> pkthdr_ptr;
00076 typedef boost::shared_array<uint8_t> bytes_ptr;
00077
00078
00079 if (next1_ == iterable_->last1_)
00080 {
00081 this->value() = boost::none_t ();
00082
00083
00084 while (next2_ != iterable_->last2_)
00085 ++next2_;
00086
00087 return;
00088 }
00089 update_coefs();
00090
00091 const tool::microseconds us (next1_->microseconds() *
00092 coefs_->first + coefs_->second);
00093 const time_values tv = iterable_->convert_(us);
00094
00095 const pcapxx::pkthdr* pcaph = next1_->pcap_header().get();
00096 const size_t caplen = pcaph->caplen;
00097 const bool swapped = need_swap(iterable_->phy_end_,
00098 pcaph->swapped);
00099 const pkthdr_ptr v_pcap_header (new pkthdr (*pcaph));
00100 const bytes_ptr v_bytes (new uint8_t[caplen]);
00101
00102 v_pcap_header->ts = tv.pcaptime;
00103 memcpy(v_bytes.get(), next1_->bytes().get(), caplen);
00104 internals::adjust(reinterpret_cast<HT*> (v_bytes.get()),
00105 caplen, swapped, tv);
00106 this->value() =
00107 value_type (us, pcapxx::frame_descriptor (v_pcap_header, v_bytes));
00108 ++next1_;
00109 }
00110
00111 template <class I1, class I2, class HT, class B1, class B2>
00112 void
00113 time_adjuster_iterator<I1, I2, HT, B1, B2>::update_coefs()
00114 {
00115 const tool::microseconds us = next1_->microseconds();
00116 const I2& last2 = iterable_->last2_;
00117
00118
00119
00120
00121
00122
00123
00124 while (next2_ != last2 and next2_->first.microseconds() <= us)
00125 {
00126 coefs_ = next2_->coefs;
00127 ++next2_;
00128 }
00129 if (not coefs_)
00130 {
00131 if (next2_ != last2)
00132 coefs_ = next2_->coefs;
00133 else
00134 throw std::runtime_error ("No reference frames: "
00135 "impossible to synchronize");
00136 }
00137 }
00138
00139 template <>
00140 inline
00141 time_converter<>
00142 time_reference<prism::header>(const pcapxx::pkthdr& pcap_header,
00143 const prism::header* bytes,
00144 tool::endian::endianness phy_end)
00145 {
00146 using tool::endian::need_swap;
00147
00148 if (pcap_header.caplen < sizeof (prism::header))
00149 return time_converter<> (pcap_header.ts, 0, 0,
00150 tool::microseconds (0));
00151
00152 const bool swapped = need_swap(phy_end, pcap_header.swapped);
00153 const uint32_t hosttime = bytes->hosttime.get(swapped);
00154 const uint32_t mactime = bytes->mactime.get(swapped);
00155
00156 return time_converter<> (pcap_header.ts, hosttime, mactime,
00157 tool::microseconds (mactime));
00158 }
00159
00160 template <>
00161 inline
00162 void
00163 adjust<prism::header>(prism::header* bytes, size_t caplen, bool swap,
00164 const time_converter<>::time_values& time)
00165 {
00166 if (caplen < sizeof (prism::header))
00167 return;
00168
00169 bytes->hosttime.set(time.hosttime, swap);
00170 bytes->mactime.set(time.mactime, swap);
00171 }
00172
00173 }
00174
00175
00176 template <class I1, class I2, class HT, class B>
00177 time_adjuster<I1, I2, HT, B>::
00178 time_adjuster(const I1& first1, const I1& last1,
00179 const I2& first2, const I2& last2,
00180 const pcapxx::frame_descriptor& tref,
00181 tool::endian::endianness phy_end):
00182 convert_ (internals::time_reference(*tref.pcap_header(),
00183 reinterpret_cast<const HT*>
00184 (tref.bytes().get()),
00185 phy_end)),
00186 phy_end_ (phy_end),
00187 first1_ (first1),
00188 last1_ (last1),
00189 first2_ (first2),
00190 last2_ (last2)
00191 {
00192 }
00193
00194 namespace internals
00195 {
00196
00197 template <class HT, class I1, class I2, class F>
00198 struct provide_time_adjuster
00199 {
00200 provide_time_adjuster(const I1& first1, const I1& last1,
00201 const I2& first2, const I2& last2,
00202 F& func,
00203 bool filter_prism,
00204 tool::endian::endianness phy_end):
00205 first1_ (first1),
00206 last1_ (last1),
00207 first2_ (first2),
00208 last2_ (last2),
00209 func_ (func),
00210 filter_prism_ (filter_prism),
00211 phy_end_ (phy_end)
00212 {
00213 }
00214
00215 template <class Synchronizer>
00216 void
00217 operator () (const Synchronizer& s)
00218 {
00219 if (first2_ == last2_)
00220 throw std::runtime_error ("No packets in reference trace. "
00221 "Cannot synchronize with no time "
00222 "reference and no unique frames");
00223 if (filter_prism_)
00224 {
00225 typedef non_noisy_prism<I2> nnp;
00226 typedef typename nnp::const_iterator n_iterator;
00227 typedef microseconds_stamper<n_iterator, HT> us_stamper;
00228 typedef typename us_stamper::const_iterator u_iterator;
00229 typedef typename Synchronizer::const_iterator s_iterator;
00230 typedef time_adjuster<u_iterator, s_iterator, HT> adjuster;
00231
00232 nnp n (first1_, last1_);
00233 us_stamper u (n.begin(), n.end(), phy_end_);
00234 adjuster a (u.begin(), u.end(),
00235 s.begin(), s.end(), *first2_, phy_end_);
00236 func_(a);
00237 }
00238 else
00239 {
00240 typedef microseconds_stamper<I2, HT> us_stamper;
00241 typedef typename us_stamper::const_iterator u_iterator;
00242 typedef typename Synchronizer::const_iterator s_iterator;
00243 typedef time_adjuster<u_iterator, s_iterator, HT> adjuster;
00244
00245 us_stamper u (first1_, last1_, phy_end_);
00246 adjuster a (u.begin(), u.end(),
00247 s.begin(), s.end(), *first2_, phy_end_);
00248 func_(a);
00249 }
00250 }
00251
00252 private:
00253 const I1& first1_;
00254 const I1& last1_;
00255 const I2& first2_;
00256 const I2& last2_;
00257 F& func_;
00258 bool filter_prism_;
00259 tool::endian::endianness phy_end_;
00260 };
00261
00262 }
00263
00264 template <class U, class HT, template <class, class, class> class Int,
00265 class I1, class I2, class F, class BL>
00266 void
00267 provide_time_adjuster(const I1& first1, const I1& last1,
00268 const I2& first2, const I2& last2,
00269 addr_mapping& mapping,
00270 F& func,
00271 bool filter_prism,
00272 tool::endian::endianness phy_end,
00273 const BL& blist)
00274 {
00275 internals::provide_time_adjuster<HT, I1, I2, F> func2 (first1, last1,
00276 first2, last2,
00277 func,
00278 filter_prism,
00279 phy_end);
00280
00281 provide_lr_synchronizer<U, HT, Int>(first1, last1,
00282 first2, last2,
00283 mapping, func2,
00284 filter_prism, phy_end, blist);
00285 }
00286
00287 }
00288
00289 }
00290
00291 }
00292
00293 #endif // ! WIFI_FRAME_FILTER_TIME_ADJUSTER_HXX_