00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef RTAP_HEADER_HXX_
00023 # define RTAP_HEADER_HXX_
00024
00025 # include "rtap_header.hh"
00026
00027 # include <stdexcept>
00028 # include <cstring>
00029
00030 # include <wipal/tool/endianness.hh>
00031
00032 namespace rtap
00033 {
00034
00035 inline
00036 size_t
00037 header::len_impl(size_t caplen, bool) const
00038 {
00039
00040 if (caplen and it_version)
00041 return caplen + 1;
00042
00043
00044 if (caplen < sizeof (rtap::header))
00045 return caplen + 1;
00046
00047 return tool::extract_little_endian_short_u(it_len);
00048 }
00049
00050 inline
00051 header::time_type
00052 header::time_get_impl(bool) const
00053 {
00054 return tsft_get(tool::extract_little_endian_short_u(it_len));
00055 }
00056
00057 inline
00058 void
00059 header::time_set_impl(const time_type& t, bool)
00060 {
00061 const size_t len = tool::extract_little_endian_short_u(it_len);
00062 void* const f = first_field(len);
00063 const uint64_t v = t.get_impl();
00064
00065 if (not tool::endian::need_swap(tool::endian::little, false))
00066 *static_cast<uint64_t*> (f) = v;
00067 else
00068 {
00069 const uint32_t lo = tool::extract_swapped_long_u(v & uint32_t (-1));
00070 const uint32_t hi = tool::extract_swapped_long_u(v >> 32);
00071 uint32_t* const f32 = static_cast<uint32_t*> (f);
00072
00073 f32[0] = lo;
00074 f32[1] = hi;
00075 }
00076 }
00077
00078 template <class D1, class D2>
00079 bool
00080 header::eq_time(const pcapxx::frame_descriptor<D1>& lhs,
00081 const pcapxx::frame_descriptor<D2>& rhs,
00082 tool::endian::endianness ,
00083 unsigned prec)
00084 {
00085 const size_t lhs_caplen = lhs.pcap_header()->caplen;
00086 const size_t rhs_caplen = rhs.pcap_header()->caplen;
00087
00088 const header* const lhs_phy = (reinterpret_cast<const header*>
00089 (lhs.bytes().get()));
00090 const header* const rhs_phy = (reinterpret_cast<const header*>
00091 (rhs.bytes().get()));
00092
00093 if (lhs_phy->len(lhs_caplen, false) > lhs_caplen or
00094 rhs_phy->len(rhs_caplen, false) > rhs_caplen)
00095 return false;
00096
00097 return std::abs(int64_t (lhs_phy->tsft_get(lhs_caplen) -
00098 rhs_phy->tsft_get(rhs_caplen))) < prec;
00099 }
00100
00101 # define WP_diff(P1, P2) (reinterpret_cast<const uint8_t*> (P2) - \
00102 reinterpret_cast<const uint8_t*> (P1))
00103
00104 inline
00105 const void*
00106 header::first_field(size_t caplen) const
00107 {
00108 const uint32_t* p = &it_present;
00109
00110 while (WP_diff(this, p + 1) < ptrdiff_t (caplen) and
00111 tool::extract_little_endian_long_u(*p) & ext)
00112 ++p;
00113 return WP_diff(this, p + 1) >= ptrdiff_t (caplen) ? 0 : p + 1;
00114 }
00115
00116 inline
00117 void*
00118 header::first_field(size_t caplen)
00119 {
00120 uint32_t* p = &it_present;
00121
00122 while (WP_diff(this, p + 1) < ptrdiff_t (caplen) and
00123 tool::extract_little_endian_long_u(*p) & ext)
00124 ++p;
00125 return WP_diff(this, p + 1) >= ptrdiff_t (caplen) ? 0 : p + 1;
00126 }
00127
00128 # undef WP_diff
00129
00130 inline
00131 uint64_t
00132 header::tsft_get(size_t caplen) const
00133 {
00134 if (not it_present & tsft)
00135 throw std::invalid_argument ("Radiotap header has no TSFT field");
00136
00137 if (caplen < sizeof (rtap::header) + 8)
00138 throw std::invalid_argument ("Truncated or inconsistent RTAP header "
00139 "(length too short w.r.t. present fields)");
00140
00141 const void* const f = first_field(caplen);
00142
00143 assert(f);
00144 if (not tool::endian::need_swap(tool::endian::little, false))
00145 return *static_cast<const uint64_t*> (f);
00146 else
00147 {
00148 const uint32_t* const f32 = static_cast<const uint32_t*> (f);
00149
00150 const uint32_t lo = tool::extract_little_endian_long_u(f32[0]);
00151 const uint32_t hi = tool::extract_little_endian_long_u(f32[1]);
00152
00153 return (uint64_t (hi) << 32) | lo;
00154 }
00155 }
00156
00157 }
00158
00159 #endif // ! RTAP_HEADER_HXX_