include/trace-tools/wifi/frame/filter/time_adjuster.hxx

00001 /*
00002  * trace-tools - A library and a set of tools to manipulate wireless traces.
00003  * Copyright (C) 2007  Universite Pierre et Marie Curie - Paris 6
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  * MA  02110-1301  USA
00019  *
00020  * Author: Thomas Claveirole <thomas.claveirole@lip6.fr>
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       } // End of namespace wifi::frame::filter::internals.
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       } // End of namespace wifi::frame::filter::internals.
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     } // End of namespace wifi::frame::filter.
00276 
00277   } // End of namespace wifi::frame.
00278 
00279 } // End of namespace wifi.
00280 
00281 #endif // ! WIFI_FRAME_FILTER_TIME_ADJUSTER_HXX_

Generated on Tue Nov 13 13:48:01 2007 for trace-tools by  doxygen 1.5.3-20071008