00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef PCAP_FRAME_DESCRIPTOR_HXX_
00023 # define PCAP_FRAME_DESCRIPTOR_HXX_
00024
00025 # include <cstring>
00026
00027 # include "frame_descriptor.hh"
00028 # include <wipal/tool/exceptions.hh>
00029 # include <wipal/tool/endianness.hh>
00030
00031 namespace pcapxx
00032 {
00033
00034 template <class PCAPDescriptor>
00035 frame_descriptor<PCAPDescriptor>::frame_descriptor(const pkthdr_ptr& h,
00036 const bytes_ptr& b,
00037 unsigned i,
00038 const PCAPDescriptor* d):
00039 data_ (new shared_data (d, i, h, b))
00040 {
00041 }
00042
00043 template <class PCAPDescriptor>
00044 template <class D>
00045 frame_descriptor<PCAPDescriptor>::
00046 frame_descriptor(const descriptor<D>& desc,
00047 std::istream& stream,
00048 unsigned idx,
00049 std::streampos* pos)
00050 {
00051 pkthdr_ptr pcap_header;
00052 bytes_ptr bytes;
00053
00054
00055 {
00056 internals::file_frame_header h;
00057
00058 if (not stream.read(reinterpret_cast<char*> (&h), sizeof (h)) or
00059 stream.gcount() != sizeof (h))
00060 throw tool::read_error ("Unreadable packet header");
00061 if (pos)
00062 *pos += sizeof (h);
00063
00064 const bool s = desc.swapped();
00065 pkthdr* const p = new pkthdr;
00066
00067
00068
00069 memset(p, 0, sizeof (*p));
00070
00071 p->ts.tv_sec = tool::extract_long_s(h.ts.tv_sec, s) + desc.zone();
00072 p->ts.tv_usec = tool::extract_long_s(h.ts.tv_usec, s);
00073 p->caplen = tool::extract_long_u(h.caplen, s);
00074 p->len = tool::extract_long_u(h.len, s);
00075 pcap_header.reset(p);
00076 }
00077
00078
00079 {
00080 const size_t caplen = pcap_header->caplen;
00081 uint8_t* const tmp = new uint8_t[caplen];
00082
00083 if (not stream.read(reinterpret_cast<char*> (tmp), caplen) or
00084 stream.gcount() != std::streampos (caplen))
00085 {
00086 delete tmp;
00087 throw tool::read_error ("Unreadable packet data");
00088 }
00089 if (pos)
00090 *pos += caplen;
00091 bytes.reset(tmp);
00092 }
00093
00094 data_.reset(new shared_data (desc.exact_ptr(), idx, pcap_header, bytes));
00095 }
00096
00097 namespace internals
00098 {
00099
00100 template <class D1, class D2>
00101 struct fd_ctor_helper
00102 {
00103 typedef typename frame_descriptor<D1>::shared_data shared_data1;
00104 typedef typename frame_descriptor<D2>::shared_data shared_data2;
00105 typedef boost::shared_ptr<shared_data1> shared_ptr1;
00106 typedef boost::shared_ptr<shared_data2> shared_ptr2;
00107
00108
00109 static void set(shared_ptr1& d1, const shared_ptr2& d2)
00110 {
00111 assert(d2);
00112
00113 d1.reset(new shared_data1 (0, 0, d2->pcap_header, d2->bytes));
00114 }
00115 };
00116
00117 template <class D>
00118 struct fd_ctor_helper<D, D>
00119 {
00120 typedef typename frame_descriptor<D>::shared_data shared_data;
00121 typedef boost::shared_ptr<shared_data> shared_ptr;
00122
00123 static void set(shared_ptr& d1, const shared_ptr& d2)
00124 {
00125 d1 = d2;
00126 }
00127 };
00128
00129 }
00130
00131 template <class PCAPDescriptor>
00132 template <class OtherDescriptor>
00133 frame_descriptor<PCAPDescriptor>::
00134 frame_descriptor(const frame_descriptor<OtherDescriptor>& fd)
00135 {
00136 typedef internals::fd_ctor_helper<PCAPDescriptor, OtherDescriptor> helper;
00137
00138 helper::set(data_, fd.data());
00139 }
00140
00141 template <class PCAPDescriptor>
00142 unsigned
00143 frame_descriptor<PCAPDescriptor>::id() const
00144 {
00145 assert(data_);
00146
00147 return data_->id;
00148 }
00149
00150 namespace internals
00151 {
00152 template <class D>
00153 bool
00154 fd_swapped_helper(const D*)
00155 {
00156 throw std::logic_error ("This code should be unreachable. "
00157 "Please fill a bug report");
00158 }
00159
00160 template <class D>
00161 bool
00162 fd_swapped_helper(const descriptor<D>* d)
00163 {
00164 return d ? d->swapped() : false;
00165 }
00166
00167 template <>
00168 inline
00169 bool
00170 fd_swapped_helper<tool::undefined_type>(const tool::undefined_type* d)
00171 {
00172 assert(not d);
00173 (void) d;
00174
00175 return false;
00176 }
00177
00178 }
00179
00180 template <class PCAPDescriptor>
00181 bool
00182 frame_descriptor<PCAPDescriptor>::swapped() const
00183 {
00184 return internals::fd_swapped_helper(desc_ptr());
00185 }
00186
00187 template <class PCAPDescriptor>
00188 const PCAPDescriptor*
00189 frame_descriptor<PCAPDescriptor>::desc_ptr() const
00190 {
00191 assert(data_);
00192
00193 return data_->desc;
00194 }
00195
00196 template <class PCAPDescriptor>
00197 const PCAPDescriptor&
00198 frame_descriptor<PCAPDescriptor>::desc() const
00199 {
00200 assert(data_);
00201
00202 if (not data_->desc)
00203 throw std::runtime_error ("Frame has no refering PCAP descriptor");
00204 return *data_->desc;
00205 }
00206
00207 template <class PCAPDescriptor>
00208 const typename frame_descriptor<PCAPDescriptor>::pkthdr_ptr&
00209 frame_descriptor<PCAPDescriptor>::pcap_header() const
00210 {
00211 assert(data_);
00212
00213 return data_->pcap_header;
00214 }
00215
00216 template <class PCAPDescriptor>
00217 const typename frame_descriptor<PCAPDescriptor>::bytes_ptr&
00218 frame_descriptor<PCAPDescriptor>::bytes() const
00219 {
00220 assert(data_);
00221
00222 return data_->bytes;
00223 }
00224
00225 namespace internals
00226 {
00227
00228 template <class D>
00229 std::ostream&
00230 fd_print_helper(std::ostream& o, const D*)
00231 {
00232 throw std::logic_error ("This code should be unreachable. "
00233 "Please fill a bug report");
00234 }
00235
00236 template <class D>
00237 std::ostream&
00238 fd_print_helper(std::ostream& o, const descriptor<D>* d)
00239 {
00240 if (d)
00241 o << d->file_name() << ':';
00242 return o;
00243 }
00244
00245 template <>
00246 inline
00247 std::ostream&
00248 fd_print_helper<tool::undefined_type>
00249 (std::ostream& o, const tool::undefined_type* d)
00250 {
00251 assert(not d);
00252 (void) d;
00253
00254 return o;
00255 }
00256
00257 }
00258
00259 template <class PCAPDescriptor>
00260 std::ostream&
00261 frame_descriptor<PCAPDescriptor>::print(std::ostream& os) const
00262 {
00263 return internals::fd_print_helper(os, desc_ptr()) << data_->id;
00264 }
00265
00266 template <class PCAPDescriptor>
00267 bool
00268 frame_descriptor<PCAPDescriptor>::
00269 operator == (const frame_descriptor& rhs) const
00270 {
00271 return
00272 0 == memcmp(pcap_header().get(), rhs.pcap_header().get(), sizeof (pkthdr))
00273 and
00274 0 == memcmp(bytes().get(), rhs.bytes().get(), pcap_header()->caplen);
00275 }
00276
00277 template <class PCAPDescriptor>
00278 bool
00279 frame_descriptor<PCAPDescriptor>::
00280 operator != (const frame_descriptor& rhs) const
00281 {
00282 return not (*this == rhs);
00283 }
00284
00285 template <class PCAPDescriptor>
00286 frame_descriptor<PCAPDescriptor>::
00287 shared_data::shared_data(const PCAPDescriptor* desc,
00288 unsigned id,
00289 const pkthdr_ptr& pcap_header,
00290 const bytes_ptr& bytes):
00291 desc (desc),
00292 id (id),
00293 pcap_header (pcap_header),
00294 bytes (bytes)
00295 {
00296 }
00297
00298 template <class PCAPDescriptor>
00299 const
00300 boost::shared_ptr<typename frame_descriptor<PCAPDescriptor>::shared_data>&
00301 frame_descriptor<PCAPDescriptor>::data() const
00302 {
00303 assert(data_);
00304
00305 return data_;
00306 }
00307
00308 template <class PCAPDescriptor>
00309 std::ostream&
00310 operator << (std::ostream& os, const frame_descriptor<PCAPDescriptor>& fd)
00311 {
00312 return fd.print(os);
00313 }
00314
00315 }
00316
00317 #endif // ! PCAP_FRAME_DESCRIPTOR_HXX_