00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_MACTIME_TRACKER_HXX_
00023 # define WIFI_MACTIME_TRACKER_HXX_
00024
00025 # include <boost/optional.hpp>
00026
00027 # include <wipal/tool/gmp_64_wrapper.hh>
00028
00029 # include "mactime_tracker.hh"
00030
00031 namespace wifi
00032 {
00033
00034 template <class Bottom>
00035 mactime_tracker<Bottom>::
00036 mactime_tracker(bool force_pcap): last_stamp_ (0),
00037 ms_count_ (0),
00038 force_pcap_ (force_pcap)
00039 {
00040 }
00041
00042 template <class Bottom>
00043 template <class UIntType>
00044 void
00045 mactime_tracker<Bottom>::tick_uint(UIntType ts)
00046 {
00047 const UIntType half_range (UIntType (1)
00048 << (sizeof (ts) * 8 - 1));
00049 const tool::microseconds ms_ts (ts);
00050 const tool::microseconds ms_last_stamp (last_stamp_);
00051
00052 ms_count_ += ms_ts - ms_last_stamp;
00053 if (ts < last_stamp_ and last_stamp_ - ts > half_range)
00054 {
00055 static boost::optional<tool::microseconds> range;
00056
00057 if (not range)
00058 {
00059 range = 1;
00060 *range <<= sizeof (ts) * 8;
00061 }
00062
00063 ms_count_ += *range;
00064 }
00065 last_stamp_ = ts;
00066 }
00067
00068 template <class Bottom>
00069 void
00070 mactime_tracker<Bottom>::tick_tv(const struct timeval& tv)
00071 {
00072 ms_count_ = tool::microseconds (tv);
00073 }
00074
00075 namespace internals
00076 {
00077
00078 template <class I, class B>
00079 struct tick_switch
00080 {
00081 template <class D>
00082 static void tick(mactime_tracker<B>& trk,
00083 const pcapxx::frame_descriptor<D>& fd,
00084 const I& )
00085 {
00086 trk.tick_tv(fd.pcap_header()->ts);
00087 }
00088 };
00089
00090 template <class B>
00091 struct tick_switch<uint32_t, B>
00092 {
00093 template <class D>
00094 static void tick(mactime_tracker<B>& trk,
00095 const pcapxx::frame_descriptor<D>& ,
00096 uint32_t ts)
00097 {
00098 trk.tick_uint(ts);
00099 }
00100 };
00101
00102 template <class B>
00103 struct tick_switch<uint64_t, B>
00104 {
00105 template <class D>
00106 static void tick(mactime_tracker<B>& trk,
00107 const pcapxx::frame_descriptor<D>& ,
00108 uint64_t ts)
00109 {
00110 trk.tick_uint(ts);
00111 }
00112 };
00113
00114 template <class B>
00115 struct tick_switch<struct timeval, B>
00116 {
00117 template <class D>
00118 static void tick(mactime_tracker<B>& trk,
00119 const pcapxx::frame_descriptor<D>& ,
00120 const struct timeval& tv)
00121 {
00122 trk.tick_tv(tv);
00123 }
00124 };
00125
00126 }
00127
00128 template <class Bottom>
00129 template <class HT, class D>
00130 void
00131 mactime_tracker<Bottom>::tick(const pcapxx::frame_descriptor<D>& frame,
00132 tool::endian::endianness phy_end)
00133 {
00134 const pcapxx::pkthdr& pcap = *frame.pcap_header();
00135
00136 if (force_pcap_)
00137 {
00138 tick_tv(pcap.ts);
00139 return;
00140 }
00141
00142 const bool swap = tool::endian::need_swap(phy_end,
00143 frame.swapped());
00144 const HT* const bytes = (reinterpret_cast<const HT*>
00145 (frame.bytes().get()));
00146
00147 if (pcap.caplen < bytes->len(pcap.caplen, swap))
00148 return;
00149
00150 internals::tick_switch<typename HT::time_type::impl_type, Bottom>::
00151 tick(*this, frame, bytes->time_get(swap).get());
00152 }
00153
00154 template <class Bottom>
00155 tool::microseconds
00156 mactime_tracker<Bottom>::microseconds() const
00157 {
00158 return ms_count_;
00159 }
00160
00161 }
00162
00163 #endif // ! WIFI_MACTIME_TRACKER_HXX_