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