00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef WSCOUT_PCAP_TRACE_HXX_
00024 # define WSCOUT_PCAP_TRACE_HXX_
00025
00026 # include <iostream>
00027
00028 # ifdef TIME_FILE_LOADING
00029 # include <boost/date_time/posix_time/posix_time.hpp>
00030 # endif // BENCH_FILE_LOADING
00031
00032 # include "wscout_pcap_trace.hh"
00033
00034 namespace wscout
00035 {
00036
00037 namespace pcap
00038 {
00039
00041 inline
00042 uint32_t
00043 swap_u32(uint32_t i)
00044 {
00045 return (((i & 0xFF) << 24) |
00046 ((i & 0xFF00) << 8) |
00047 ((i & 0xFF0000) >> 8) |
00048 (i >> 24));
00049 }
00050
00052 inline
00053 int32_t
00054 swap_s32(int32_t i)
00055 {
00056 return int32_t (swap_u32(uint32_t (i)));
00057 }
00058
00059 namespace
00060 {
00061
00062 struct DummySetup
00063 {
00064 inline
00065 void
00066 operator () (std::streampos, std::streampos)
00067 {
00068 }
00069 };
00070
00071 struct DummyUpdate
00072 {
00073 inline
00074 const std::string*
00075 operator () (std::streampos)
00076 {
00077 return 0;
00078 }
00079 };
00080
00081 }
00082
00083 inline
00084 Trace::invalid_operation::invalid_operation(const std::string& s):
00085 std::runtime_error (s)
00086 {
00087 }
00088
00089 inline
00090 Trace::interrupted::interrupted(const std::string& s):
00091 std::runtime_error (s)
00092 {
00093 }
00094
00095 inline
00096 Trace::Trace(const std::string& filename)
00097 {
00098 DummySetup pi_setup;
00099 DummyUpdate pi_update;
00100
00101 setup(filename, pi_setup, pi_update);
00102 }
00103
00104 template <typename ProgressInfoSetupType,
00105 typename ProgressInfoUpdateType>
00106 Trace::Trace(const std::string& filename,
00107 ProgressInfoSetupType& pi_setup,
00108 ProgressInfoUpdateType& pi_update)
00109 {
00110 setup(filename, pi_setup, pi_update);
00111 }
00112
00113 template <typename ProgressInfoSetupType,
00114 typename ProgressInfoUpdateType>
00115 void
00116 Trace::setup(const std::string& filename,
00117 ProgressInfoSetupType& pi_setup,
00118 ProgressInfoUpdateType& pi_update)
00119 {
00120 pcap_file_header h;
00121
00122 file_.open(filename.c_str());
00123 if (not file_)
00124 throw invalid_operation ("Open failed");
00125 file_name_ = filename;
00126 if (not file_.seekg(0, std::ios::end))
00127 throw invalid_operation ("Seek operation failed");
00128 file_size_ = file_.tellg();
00129 if (not file_.seekg(0, std::ios::beg))
00130 throw invalid_operation ("Seek operation failed");
00131
00132 if (not file_.read(reinterpret_cast<char*> (&h), sizeof (h)) or
00133 file_.gcount() != sizeof (h))
00134 throw invalid_operation ("Unreadable PCAP file header");
00135 switch (h.magic)
00136 {
00137 case 0xa1b2c3d4:
00138 swap_ = false;
00139 break;
00140 case 0xd4c3b2a1:
00141 swap_ = true;
00142 break;
00143 default:
00144 throw std::invalid_argument ("Not a PCAP trace");
00145 }
00146 zone_ = swap_ ? swap_s32(h.thiszone) : h.thiszone;
00147 type_ = link_type (swap_ ? swap_s32(h.linktype) : h.linktype);
00148
00149 setup_marks(pi_setup, pi_update);
00150 }
00151
00152 template <typename ProgressInfoSetupType,
00153 typename ProgressInfoUpdateType>
00154 void
00155 Trace::setup_marks(ProgressInfoSetupType& pi_setup,
00156 ProgressInfoUpdateType& pi_update)
00157 {
00158 # ifdef TIME_FILE_LOADING
00159 using namespace boost::posix_time;
00160
00161 const ptime start = microsec_clock::universal_time();
00162 # endif // TIME_FILE_LOADING
00163
00164 pkt_count_ = 0;
00165
00166 {
00167 const std::streampos first_packet_offset = file_.tellg();
00168
00169 marks_.push_back(first_packet_offset);
00170 pi_setup(first_packet_offset, file_size_);
00171 }
00172
00173 pcap_packet_header h;
00174
00175 while (file_.read(reinterpret_cast<char*> (&h), sizeof (h)))
00176 {
00177 if (file_.gcount() != sizeof (h))
00178 {
00179 handle_truncation("truncated packet header");
00180 break;
00181 }
00182
00183 char junk[junk_len];
00184
00185 if (swap_)
00186 h.caplen = swap_u32(h.caplen);
00187 while(h.caplen)
00188 {
00189 size_t to_read = std::min(sizeof (junk),
00190 size_t (h.caplen));
00191
00192 if (not file_.read(junk, to_read))
00193 {
00194 handle_truncation("truncated packet data");
00195 break;
00196 }
00197 h.caplen -= to_read;
00198 }
00199
00200 if (++pkt_count_ % mark_step == 0)
00201 {
00202 const std::streampos current_offset = file_.tellg();
00203
00204 marks_.push_back(current_offset);
00205 if (const std::string* e = pi_update(current_offset))
00206 throw interrupted (*e);
00207 }
00208 }
00209 pi_update(file_size_);
00210 if (file_.bad())
00211 throw invalid_operation ("Unrecoverable corruption in PCAP file");
00212 file_.clear();
00213
00214 # ifdef TIME_FILE_LOADING
00215 std::cerr << (microsec_clock::universal_time() - start) << std::endl;
00216 # endif // TIME_FILE_LOADING
00217 }
00218
00219 }
00220
00221 }
00222
00223 #endif // ! WSCOUT_PCAP_TRACE_HXX_