00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef PCAP_FILE_ITERATOR_HXX_
00023 # define PCAP_FILE_ITERATOR_HXX_
00024
00025 # include <boost/lexical_cast.hpp>
00026
00027 # include "file_iterator.hh"
00028
00029 # include <wipal/pcap/base.hh>
00030 # include <wipal/tool/exceptions.hh>
00031
00032 namespace wpl
00033 {
00034
00035 namespace pcap
00036 {
00037
00038 namespace internals
00039 {
00040
00041 template <class S, class B>
00042 file_iterator<S, B>::file_iterator(const iterable_type& stream,
00043 bool end):
00044 stream_ (&stream)
00045 {
00046 if (not end)
00047 {
00048 pos_ = sizeof (file_header);
00049 count_ = 0;
00050 increment();
00051 }
00052 }
00053
00054 template <class S, class B>
00055 file_iterator<S, B>::file_iterator(const iterable_type& stream,
00056 const std::streampos& pos,
00057 unsigned count,
00058 std::istream* const istream):
00059 stream_ (&stream),
00060 input_ (istream),
00061 pos_ (pos),
00062 count_ (count)
00063 {
00064 increment();
00065 }
00066
00067 template <class S, class B>
00068 file_iterator<S, B>::file_iterator(const file_iterator& it):
00069 stream_ (it.stream_)
00070 {
00071 if (it.value())
00072 {
00073 pos_ = it.pos_;
00074 count_ = it.count_;
00075 this->value() = it.value();
00076 }
00077 }
00078
00079 template <class S, class B>
00080 file_iterator<S, B>&
00081 file_iterator<S, B>::operator = (const file_iterator& rhs)
00082 {
00083 if (&rhs == this)
00084 return *this;
00085
00086 stream_ = rhs.stream_;
00087 input_.reset();
00088 if ((this->value() = rhs.value()))
00089 {
00090 pos_ = rhs.pos_;
00091 count_ = rhs.count_;
00092 }
00093 return *this;
00094 }
00095
00096 template <class S, class B>
00097 bool
00098 file_iterator<S, B>::equal(const file_iterator& rhs) const
00099 {
00100 if (not rhs.value())
00101 return not this->value();
00102 return this->value() and pos_ == rhs.pos_;
00103 }
00104
00105 template <class S, class B>
00106 void
00107 file_iterator<S, B>::increment()
00108 {
00109 try
00110 {
00111 increment_pcap();
00112 }
00113 catch (const tool::read_error&)
00114 {
00115 if (stream().eof())
00116 this->value() = boost::none_t ();
00117 else
00118 throw;
00119 }
00120 }
00121
00122 template <class S, class B>
00123 std::istream&
00124 file_iterator<S, B>::stream()
00125 {
00126 if (not input_.get())
00127 {
00128 input_.reset(stream_->stream(false));
00129 if (not input_->seekg(pos_, std::ios::beg))
00130 throw tool::seek_error("Seek operation failed");
00131 }
00132 return *input_;
00133 }
00134
00135 template <class S, class B>
00136 void
00137 file_iterator<S, B>::increment_pcap()
00138 {
00139 std::istream& i = stream();
00140 file_frame_header h;
00141
00142 if (not i.read(reinterpret_cast<char*> (&h), sizeof (h)) or
00143 i.gcount() != sizeof (h))
00144 throw tool::read_error ("Unreadable packet header");
00145 pos_ += sizeof (h);
00146
00147 const bool swapped = stream_->swapped();
00148 const size_t caplen = tool::extract_long_u(h.caplen, swapped);
00149
00150 if (caplen > max_packet_size)
00151 throw tool::bad_file("Packet size too large to make sense (" +
00152 boost::lexical_cast<std::string>(caplen) + ")");
00153
00154
00155 assert(caplen <= value_type::max_size);
00156
00157 const unsigned id = ++count_;
00158 const unsigned sec = (tool::extract_long_s(h.ts.tv_sec, swapped) +
00159 stream_->zone());
00160 const unsigned usec = tool::extract_long_s(h.ts.tv_usec, swapped);
00161 const size_t len = tool::extract_long_u(h.len, swapped);
00162
00163 boost::optional<value_type>& v = this->value();
00164
00165 if (not v or not v->unique())
00166 v = value_type (id, sec, usec, caplen, len, stream_);
00167 else
00168 {
00169 pkt::metadata& m = v->meta();
00170
00171 m.id = id;
00172 m.ts.tv_sec = sec;
00173 m.ts.tv_usec = usec;
00174 m.caplen = caplen;
00175 m.len = len;
00176 }
00177
00178 if (not i.read(static_cast<char*> (v->bytes()), caplen) or
00179 i.gcount() != std::streampos (caplen))
00180 throw tool::read_error ("Unreadable packet data");
00181 pos_ += caplen;
00182 }
00183
00184 }
00185
00186 }
00187
00188 }
00189
00190 #endif // ! PCAP_FILE_ITERATOR_HXX_