00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FILTER_TIME_ADJUSTER_HXX_
00023 # define 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/filter/timetracker.hh>
00031 # include <wipal/filter/linear_regression_synchronizer.hh>
00032
00033 namespace wpl
00034 {
00035
00036 namespace filter
00037 {
00038
00039 namespace internals
00040 {
00041
00042 template <class I1, class I2, class HT, class B1, class B2>
00043 time_adjuster_iterator<I1, I2, HT, B1, B2>::
00044 time_adjuster_iterator(const iterable_type& i, bool end):
00045 super_type (),
00046 iterable_ (&i),
00047 next1_ (end ? i.last1_ : i.first1_),
00048 next2_ (end ? i.last2_ : i.first2_)
00049 {
00050 if (not end)
00051 increment();
00052 }
00053
00054 template <class I1, class I2, class HT, class B1, class B2>
00055 bool
00056 time_adjuster_iterator<I1, I2, HT, B1, B2>::
00057 equal(const time_adjuster_iterator& rhs) const
00058 {
00059 if (not rhs.value())
00060 return not this->value();
00061 return next1_ == rhs.next1_;
00062 }
00063
00064 template <class I1, class I2, class HT, class B1, class B2>
00065 void
00066 time_adjuster_iterator<I1, I2, HT, B1, B2>::increment()
00067 {
00068 using tool::end::endianness;
00069
00070 typedef typename wifi::time_converter<HT>::time_values time_values;
00071 typedef typename I1::value_type::original_type packet;
00072
00073 if (next1_ == iterable_->last1_)
00074 {
00075 this->value() = boost::none_t ();
00076
00077
00078 while (next2_ != iterable_->last2_)
00079 ++next2_;
00080
00081 return;
00082 }
00083 update_coefs();
00084
00085 const tool::microseconds us (next1_->microseconds() * coefs_->first +
00086 coefs_->second);
00087 const time_values tv = iterable_->convert_(us);
00088 const bool swapped = tool::need_swap(iterable_->phy_end_,
00089 next1_->swapped());
00090
00091 boost::optional<value_type>& v = this->value();
00092
00093 if (not v or not v->unique())
00094 v = value_type (us, packet (next1_->meta()));
00095 else
00096 {
00097 v->microseconds() = us;
00098 v->meta() = next1_->meta();
00099 }
00100 memcpy(v->bytes(), next1_->bytes(), next1_->meta().caplen);
00101 internals::adjust(v->meta(), static_cast<HT*> (v->bytes()),
00102 swapped, tv);
00103 ++next1_;
00104 }
00105
00106 template <class I1, class I2, class HT, class B1, class B2>
00107 void
00108 time_adjuster_iterator<I1, I2, HT, B1, B2>::update_coefs()
00109 {
00110 const tool::microseconds us = next1_->microseconds();
00111 const I2& last2 = iterable_->last2_;
00112
00113
00114
00115
00116
00117
00118
00119 while (next2_ != last2 and next2_->first.microseconds() <= us)
00120 {
00121 coefs_ = next2_->coefs;
00122 ++next2_;
00123 }
00124 if (not coefs_)
00125 {
00126 if (next2_ != last2)
00127 coefs_ = next2_->coefs;
00128 else
00129 throw std::runtime_error ("No reference frames: "
00130 "impossible to synchronize");
00131 }
00132 }
00133
00134 template <class HT, class S>
00135 wifi::time_converter<HT>
00136 time_reference(const pkt::packet<S>& p,
00137 tool::end::endianness phy_end,
00138 bool pcap_tstamps)
00139 {
00140 using tool::need_swap;
00141 typedef typename HT::time_type time_type;
00142
00143 const pkt::metadata& m = p.meta();
00144
00145 const HT* const bytes = static_cast<const HT*> (p.bytes());
00146 const bool swapped = need_swap(phy_end, p.swapped());
00147
00148 if (m.caplen < bytes->len(m.caplen, swapped))
00149 throw std::runtime_error ("First frame too short to make a "
00150 "suitable time reference");
00151
00152 time_type time = bytes->time_get(swapped);
00153 phy::timetracker<> tracker (pcap_tstamps);
00154
00155 tracker.tick<HT>(p, phy_end);
00156 return wifi::time_converter<HT> (m.ts, time, tracker.microseconds());
00157 }
00158
00159 template <class HT>
00160 inline
00161 void
00162 adjust(pkt::metadata& meta,
00163 HT* bytes,
00164 bool swap,
00165 const typename wifi::time_converter<HT>::time_values& tv)
00166 {
00167 meta.ts = tv.pcap_time;
00168
00169 if (meta.caplen < bytes->len(meta.caplen, swap))
00170 return;
00171 bytes->time_set(tv.phy_time, swap);
00172 }
00173
00174 }
00175
00176
00177 template <class I1, class I2, class HT, class B>
00178 template <class S>
00179 time_adjuster<I1, I2, HT, B>::
00180 time_adjuster(const I1& first1, const I1& last1,
00181 const I2& first2, const I2& last2,
00182 const pkt::packet<S>& tref,
00183 tool::end::endianness phy_end,
00184 bool pcap_tstamps):
00185 convert_ (internals::time_reference<HT>(tref, phy_end, pcap_tstamps)),
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 time_adjuster_wrapper
00199 {
00200 time_adjuster_wrapper(const I1& first1, const I1& last1,
00201 const I2& first2, const I2& last2,
00202 opt::list& options,
00203 F& func):
00204 first1_ (first1),
00205 last1_ (last1),
00206 first2_ (first2),
00207 last2_ (last2),
00208 options_ (options),
00209 func_ (func)
00210 {
00211 }
00212
00213 template <class Synchronizer>
00214 void
00215 operator () (const Synchronizer& s)
00216 {
00217 typedef tool::end::endianness endianness;
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
00224 const endianness& end = options_["endianness"].get<endianness>();
00225 const bool pcts = not options_["phy_tstamps"].get<bool>();
00226
00227 if (options_["ignore_noisy_prism"].get<bool>())
00228 {
00229 typedef non_noisy_prism<I1> nnp;
00230 typedef typename nnp::const_iterator nnp_iterator;
00231 typedef timetracker<nnp_iterator, HT> tt;
00232 typedef typename tt::const_iterator tt_iterator;
00233 typedef typename Synchronizer::const_iterator s_iterator;
00234 typedef time_adjuster<tt_iterator, s_iterator, HT> adjuster;
00235
00236 nnp n (first1_, last1_);
00237 tt u (n.begin(), n.end(), end, pcts);
00238 adjuster a (u.begin(), u.end(), s.begin(), s.end(),
00239 *first2_, end, pcts);
00240 func_(a);
00241 }
00242 else
00243 {
00244 typedef timetracker<I1, HT> tt;
00245 typedef typename tt::const_iterator tt_iterator;
00246 typedef typename Synchronizer::const_iterator s_iterator;
00247 typedef time_adjuster<tt_iterator, s_iterator, HT> adjuster;
00248
00249 tt u (first1_, last1_, end, pcts);
00250 adjuster a (u.begin(), u.end(), s.begin(), s.end(),
00251 *first2_, end, pcts);
00252 func_(a);
00253 }
00254 }
00255
00256 private:
00257 const I1& first1_;
00258 const I1& last1_;
00259 const I2& first2_;
00260 const I2& last2_;
00261 opt::list& options_;
00262 F& func_;
00263 };
00264
00265 }
00266
00267 template <class U, class HT, template <class, class, class> class Int,
00268 class I1, class I2, class F>
00269 void
00270 provide_time_adjuster(const I1& first1, const I1& last1,
00271 const I2& first2, const I2& last2,
00272 opt::list& options,
00273 F& func)
00274 {
00275 typedef internals::time_adjuster_wrapper<HT, I1, I2, F> wrapper;
00276
00277 wrapper wrap (first1, last1, first2, last2, options, func);
00278
00279 provide_lr_synchronizer<U, HT, Int>(first1, last1,
00280 first2, last2, options, wrap);
00281 }
00282
00283 }
00284
00285 }
00286
00287 #endif // ! FILTER_TIME_ADJUSTER_HXX_