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