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