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 typedef pcapxx::frame_descriptor<> fd_type;
00078
00079
00080
00081 if (next1_ == iterable_->last1_)
00082 {
00083 this->value() = boost::none_t ();
00084
00085
00086 while (next2_ != iterable_->last2_)
00087 ++next2_;
00088
00089 return;
00090 }
00091 update_coefs();
00092
00093 const tool::microseconds us (next1_->microseconds() *
00094 coefs_->first + coefs_->second);
00095 const time_values tv = iterable_->convert_(us);
00096
00097 const pcapxx::pkthdr* pcaph = next1_->pcap_header().get();
00098 const size_t caplen = pcaph->caplen;
00099 const bool swapped = need_swap(iterable_->phy_end_,
00100 next1_->swapped());
00101 const pkthdr_ptr v_pcap_header (new pkthdr (*pcaph));
00102 const bytes_ptr v_bytes (new uint8_t[caplen]);
00103
00104 memcpy(v_bytes.get(), next1_->bytes().get(), caplen);
00105 internals::adjust(*v_pcap_header,
00106 reinterpret_cast<HT*> (v_bytes.get()),
00107 swapped, tv);
00108
00109 this->value() = value_type (us, fd_type (v_pcap_header, v_bytes));
00110 ++next1_;
00111 }
00112
00113 template <class I1, class I2, class HT, class B1, class B2>
00114 void
00115 time_adjuster_iterator<I1, I2, HT, B1, B2>::update_coefs()
00116 {
00117 const tool::microseconds us = next1_->microseconds();
00118 const I2& last2 = iterable_->last2_;
00119
00120
00121
00122
00123
00124
00125
00126 while (next2_ != last2 and next2_->first.microseconds() <= us)
00127 {
00128 coefs_ = next2_->coefs;
00129 ++next2_;
00130 }
00131 if (not coefs_)
00132 {
00133 if (next2_ != last2)
00134 coefs_ = next2_->coefs;
00135 else
00136 throw std::runtime_error ("No reference frames: "
00137 "impossible to synchronize");
00138 }
00139 }
00140
00141 template <class HT, class D>
00142 time_converter<HT>
00143 time_reference(const pcapxx::frame_descriptor<D>& fd,
00144 tool::endian::endianness phy_end)
00145 {
00146 using tool::endian::need_swap;
00147 typedef typename HT::time_type time_type;
00148
00149 const pcapxx::pkthdr& pcap = *fd.pcap_header();
00150
00151 const HT* const bytes = reinterpret_cast<const HT*> (fd.
00152 bytes().
00153 get());
00154 const bool swapped = need_swap(phy_end, fd.swapped());
00155
00156 if (pcap.caplen < bytes->len(pcap.caplen, swapped))
00157 throw std::runtime_error ("First frame too short to make a "
00158 "suitable time reference");
00159
00160 time_type time = bytes->time_get(swapped);
00161 mactime_tracker<> tracker;
00162
00163 tracker.tick<HT>(fd, phy_end);
00164 return time_converter<HT> (pcap.ts, time, tracker.microseconds());
00165 }
00166
00167 template <class HT>
00168 inline
00169 void
00170 adjust(pcapxx::pkthdr& pcap,
00171 HT* bytes,
00172 bool swap,
00173 const typename time_converter<HT>::time_values& tv)
00174 {
00175 pcap.ts = tv.pcap_time;
00176
00177 if (pcap.caplen < bytes->len(pcap.caplen, swap))
00178 return;
00179 bytes->time_set(tv.phy_time, swap);
00180 }
00181
00182 }
00183
00184
00185 template <class I1, class I2, class HT, class B>
00186 template <class D>
00187 time_adjuster<I1, I2, HT, B>::
00188 time_adjuster(const I1& first1, const I1& last1,
00189 const I2& first2, const I2& last2,
00190 const pcapxx::frame_descriptor<D>& tref,
00191 tool::endian::endianness phy_end):
00192 convert_ (internals::time_reference<HT>(tref, phy_end)),
00193 phy_end_ (phy_end),
00194 first1_ (first1),
00195 last1_ (last1),
00196 first2_ (first2),
00197 last2_ (last2)
00198 {
00199 }
00200
00201 namespace internals
00202 {
00203
00204 template <class HT, class I1, class I2, class F>
00205 struct provide_time_adjuster
00206 {
00207 provide_time_adjuster(const I1& first1, const I1& last1,
00208 const I2& first2, const I2& last2,
00209 F& func,
00210 bool filter_prism,
00211 tool::endian::endianness phy_end):
00212 first1_ (first1),
00213 last1_ (last1),
00214 first2_ (first2),
00215 last2_ (last2),
00216 func_ (func),
00217 filter_prism_ (filter_prism),
00218 phy_end_ (phy_end)
00219 {
00220 }
00221
00222 template <class Synchronizer>
00223 void
00224 operator () (const Synchronizer& s)
00225 {
00226 if (first2_ == last2_)
00227 throw std::runtime_error ("No packets in reference trace. "
00228 "Cannot synchronize with no time "
00229 "reference and no unique frames");
00230 if (filter_prism_)
00231 {
00232 typedef non_noisy_prism<I1> nnp;
00233 typedef typename nnp::const_iterator n_iterator;
00234 typedef microseconds_stamper<n_iterator, HT> us_stamper;
00235 typedef typename us_stamper::const_iterator u_iterator;
00236 typedef typename Synchronizer::const_iterator s_iterator;
00237 typedef time_adjuster<u_iterator, s_iterator, HT> adjuster;
00238
00239 nnp n (first1_, last1_);
00240 us_stamper u (n.begin(), n.end(), phy_end_);
00241 adjuster a (u.begin(), u.end(),
00242 s.begin(), s.end(), *first2_, phy_end_);
00243 func_(a);
00244 }
00245 else
00246 {
00247 typedef microseconds_stamper<I1, HT> us_stamper;
00248 typedef typename us_stamper::const_iterator u_iterator;
00249 typedef typename Synchronizer::const_iterator s_iterator;
00250 typedef time_adjuster<u_iterator, s_iterator, HT> adjuster;
00251
00252 us_stamper u (first1_, last1_, phy_end_);
00253 adjuster a (u.begin(), u.end(),
00254 s.begin(), s.end(), *first2_, phy_end_);
00255 func_(a);
00256 }
00257 }
00258
00259 private:
00260 const I1& first1_;
00261 const I1& last1_;
00262 const I2& first2_;
00263 const I2& last2_;
00264 F& func_;
00265 bool filter_prism_;
00266 tool::endian::endianness phy_end_;
00267 };
00268
00269 }
00270
00271 template <class U, class HT, template <class, class, class> class Int,
00272 class I1, class I2, class F, class BL>
00273 void
00274 provide_time_adjuster(const I1& first1, const I1& last1,
00275 const I2& first2, const I2& last2,
00276 addr_mapping& mapping,
00277 F& func,
00278 bool filter_prism,
00279 tool::endian::endianness phy_end,
00280 const BL& blist)
00281 {
00282 internals::provide_time_adjuster<HT, I1, I2, F> func2 (first1, last1,
00283 first2, last2,
00284 func,
00285 filter_prism,
00286 phy_end);
00287
00288 provide_lr_synchronizer<U, HT, Int>(first1, last1,
00289 first2, last2,
00290 mapping, func2,
00291 filter_prism, phy_end, blist);
00292 }
00293
00294 }
00295
00296 }
00297
00298 }
00299
00300 #endif // ! WIFI_FRAME_FILTER_TIME_ADJUSTER_HXX_