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<HT>::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 memcpy(v_bytes.get(), next1_->bytes().get(), caplen);
00103 internals::adjust(*v_pcap_header,
00104 reinterpret_cast<HT*> (v_bytes.get()),
00105 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 <class HT>
00140 inline
00141 time_converter<HT>
00142 time_reference(const pcapxx::frame_descriptor& fd,
00143 tool::endian::endianness phy_end)
00144 {
00145 using tool::endian::need_swap;
00146 typedef typename HT::time_type time_type;
00147
00148 const pcapxx::pkthdr& pcap = *fd.pcap_header();
00149
00150 const HT* const bytes = reinterpret_cast<const HT*> (fd.
00151 bytes().
00152 get());
00153 const bool swapped = need_swap(phy_end, pcap.swapped);
00154
00155 if (pcap.caplen < bytes->len(pcap.caplen, swapped))
00156 throw std::runtime_error ("First frame too short to make a "
00157 "suitable time reference");
00158
00159 time_type time = bytes->time_get(swapped);
00160 mactime_tracker<> tracker;
00161
00162 tracker.tick<HT>(fd, phy_end);
00163 return time_converter<HT> (pcap.ts, time, tracker.microseconds());
00164 }
00165
00166 template <class HT>
00167 inline
00168 void
00169 adjust(pcapxx::pkthdr& pcap,
00170 HT* bytes,
00171 bool swap,
00172 const typename time_converter<HT>::time_values& tv)
00173 {
00174 pcap.ts = tv.pcap_time;
00175
00176 if (pcap.caplen < bytes->len(pcap.caplen, swap))
00177 return;
00178 bytes->time_set(tv.phy_time, swap);
00179 }
00180
00181 }
00182
00183
00184 template <class I1, class I2, class HT, class B>
00185 time_adjuster<I1, I2, HT, B>::
00186 time_adjuster(const I1& first1, const I1& last1,
00187 const I2& first2, const I2& last2,
00188 const pcapxx::frame_descriptor& tref,
00189 tool::endian::endianness phy_end):
00190 convert_ (internals::time_reference<HT>(tref, phy_end)),
00191 phy_end_ (phy_end),
00192 first1_ (first1),
00193 last1_ (last1),
00194 first2_ (first2),
00195 last2_ (last2)
00196 {
00197 }
00198
00199 namespace internals
00200 {
00201
00202 template <class HT, class I1, class I2, class F>
00203 struct provide_time_adjuster
00204 {
00205 provide_time_adjuster(const I1& first1, const I1& last1,
00206 const I2& first2, const I2& last2,
00207 F& func,
00208 bool filter_prism,
00209 tool::endian::endianness phy_end):
00210 first1_ (first1),
00211 last1_ (last1),
00212 first2_ (first2),
00213 last2_ (last2),
00214 func_ (func),
00215 filter_prism_ (filter_prism),
00216 phy_end_ (phy_end)
00217 {
00218 }
00219
00220 template <class Synchronizer>
00221 void
00222 operator () (const Synchronizer& s)
00223 {
00224 if (first2_ == last2_)
00225 throw std::runtime_error ("No packets in reference trace. "
00226 "Cannot synchronize with no time "
00227 "reference and no unique frames");
00228 if (filter_prism_)
00229 {
00230 typedef non_noisy_prism<I2> nnp;
00231 typedef typename nnp::const_iterator n_iterator;
00232 typedef microseconds_stamper<n_iterator, HT> us_stamper;
00233 typedef typename us_stamper::const_iterator u_iterator;
00234 typedef typename Synchronizer::const_iterator s_iterator;
00235 typedef time_adjuster<u_iterator, s_iterator, HT> adjuster;
00236
00237 nnp n (first1_, last1_);
00238 us_stamper u (n.begin(), n.end(), phy_end_);
00239 adjuster a (u.begin(), u.end(),
00240 s.begin(), s.end(), *first2_, phy_end_);
00241 func_(a);
00242 }
00243 else
00244 {
00245 typedef microseconds_stamper<I2, HT> us_stamper;
00246 typedef typename us_stamper::const_iterator u_iterator;
00247 typedef typename Synchronizer::const_iterator s_iterator;
00248 typedef time_adjuster<u_iterator, s_iterator, HT> adjuster;
00249
00250 us_stamper u (first1_, last1_, phy_end_);
00251 adjuster a (u.begin(), u.end(),
00252 s.begin(), s.end(), *first2_, phy_end_);
00253 func_(a);
00254 }
00255 }
00256
00257 private:
00258 const I1& first1_;
00259 const I1& last1_;
00260 const I2& first2_;
00261 const I2& last2_;
00262 F& func_;
00263 bool filter_prism_;
00264 tool::endian::endianness phy_end_;
00265 };
00266
00267 }
00268
00269 template <class U, class HT, template <class, class, class> class Int,
00270 class I1, class I2, class F, class BL>
00271 void
00272 provide_time_adjuster(const I1& first1, const I1& last1,
00273 const I2& first2, const I2& last2,
00274 addr_mapping& mapping,
00275 F& func,
00276 bool filter_prism,
00277 tool::endian::endianness phy_end,
00278 const BL& blist)
00279 {
00280 internals::provide_time_adjuster<HT, I1, I2, F> func2 (first1, last1,
00281 first2, last2,
00282 func,
00283 filter_prism,
00284 phy_end);
00285
00286 provide_lr_synchronizer<U, HT, Int>(first1, last1,
00287 first2, last2,
00288 mapping, func2,
00289 filter_prism, phy_end, blist);
00290 }
00291
00292 }
00293
00294 }
00295
00296 }
00297
00298 #endif // ! WIFI_FRAME_FILTER_TIME_ADJUSTER_HXX_