diff --git a/decoder/src/lib/op25.i b/decoder/src/lib/op25.i index 4d61722..f9be160 100644 --- a/decoder/src/lib/op25.i +++ b/decoder/src/lib/op25.i @@ -84,7 +84,7 @@ GR_SWIG_BLOCK_MAGIC(op25, pcap_source_b); /* * Publicly-accesible constuctor function for op25_pcap_source. */ -op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay, bool repeat); +op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay); /* * The op25_pcap_source block. Reads symbols from a tcpdump-formatted @@ -93,7 +93,7 @@ op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay, b class op25_pcap_source_b : public gr_sync_block { private: - op25_pcap_source_b(const char *path); + op25_pcap_source_b(const char *path, float delay); }; // ---------------------------------------------------------------- diff --git a/decoder/src/lib/op25_pcap_source_b.cc b/decoder/src/lib/op25_pcap_source_b.cc index ad6ef30..5704306 100644 --- a/decoder/src/lib/op25_pcap_source_b.cc +++ b/decoder/src/lib/op25_pcap_source_b.cc @@ -21,6 +21,8 @@ * 02110-1301, USA. */ +#define __STDC_CONSTANT_MACROS + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -32,23 +34,23 @@ #include #include #include +#include #include #include +#define PCAP_DONT_INCLUDE_PCAP_BPF_H +#include + using namespace std; op25_pcap_source_b_sptr -op25_make_pcap_source_b(const char *path, float delay, bool repeat) +op25_make_pcap_source_b(const char *path, float delay) { - return op25_pcap_source_b_sptr(new op25_pcap_source_b(path, delay, repeat)); + return op25_pcap_source_b_sptr(new op25_pcap_source_b(path, delay)); } op25_pcap_source_b::~op25_pcap_source_b() { - if(pcap_) { - pcap_close(pcap_); - pcap_ = NULL; - } } int @@ -56,80 +58,58 @@ op25_pcap_source_b::work(int nof_output_items, gr_vector_const_void_star& input_ { try { uint8_t *out = reinterpret_cast(output_items[0]); + const size_t SYMS_AVAIL = symbols_.size(); const size_t SYMS_REQD = static_cast(nof_output_items); - if(symbols_.size() < SYMS_REQD) { - read_at_least(SYMS_REQD); + for(size_t i = 0; i < SYMS_REQD; ++i) { + out[i] = symbols_[loc_++]; + loc_ %= SYMS_AVAIL; } - const size_t SYMS_AVAIL = min(symbols_.size(), SYMS_REQD); - copy(symbols_.begin(), symbols_.begin() + SYMS_AVAIL, out); - symbols_.erase(symbols_.begin(), symbols_.begin() + SYMS_AVAIL); - fill(out + SYMS_AVAIL, out + SYMS_REQD, 0); - return(0 == SYMS_AVAIL ? -1 : SYMS_REQD); + return SYMS_REQD; } catch(const std::exception& x) { cerr << x.what() << endl; - exit(1); + exit(EXIT_FAILURE); } catch(...) { cerr << "unhandled exception" << endl; - exit(2); + exit(EXIT_FAILURE); } } -op25_pcap_source_b::op25_pcap_source_b(const char *path, float delay, bool repeat) : + +op25_pcap_source_b::op25_pcap_source_b(const char *path, float delay) : gr_sync_block ("pcap_source_b", gr_make_io_signature (0, 0, 0), gr_make_io_signature (1, 1, sizeof(uint8_t))), - path_(path), - DELAY_(delay), - repeat_(repeat), - pcap_(NULL), - prev_is_present_(false), - SYMBOLS_PER_SEC_(4800.0) + loc_(0), + SYMBOLS_PER_SEC_(4800.0), + symbols_(delay * SYMBOLS_PER_SEC_, 0) { + pcap_t *pcap; char err[PCAP_ERRBUF_SIZE]; - pcap_ = pcap_open_offline(path_.c_str(), err); -} - -float -op25_pcap_source_b::ifs(const struct pcap_pkthdr& NOW, const struct pcap_pkthdr& PREV, const size_t HEADER_SZ) const -{ - double t1 = (PREV.ts.tv_usec / 1e6); - double adj = (NOW.len - HEADER_SZ) * 4.0 / SYMBOLS_PER_SEC_; - double t2 = (NOW.ts.tv_sec - PREV.ts.tv_sec) + (NOW.ts.tv_usec / 1e6); - return static_cast(t2 - adj - t1); -} - -uint_least32_t -op25_pcap_source_b::read_at_least(const size_t NSYMS_REQD) -{ - size_t n = 0; - struct pcap_pkthdr hdr; - const size_t ETHERNET_SZ = 14; - while(pcap_ && n < NSYMS_REQD) { - const uint8_t *octets = pcap_next(pcap_, &hdr); - if(octets) { - // push inter-frame silence symbols - const float N = (prev_is_present_ ? ifs(hdr, prev_, ETHERNET_SZ) : DELAY_); - const uint_least32_t NSYMS = roundl(N * (1 / SYMBOLS_PER_SEC_)); - for(uint_least32_t i = 0; i < NSYMS; ++i, ++n) { - symbols_.push_back(0); - } - // push symbols from frame payload MSB first - for(size_t i = ETHERNET_SZ; i < hdr.caplen; ++i, ++n) { - for(int16_t j = 6; j >= 0; j -= 2) { - dibit d = (octets[i] >> j) & 0x3; - symbols_.push_back(d); + pcap = pcap_open_offline(path, err); + if(pcap) { + struct pcap_pkthdr hdr; + for(const uint8_t *octets; octets = pcap_next(pcap, &hdr);) { + const size_t ETHERNET_SZ = 14; + const size_t IP_SZ = 20; + const size_t UDP_SZ = 8; + const size_t P25CAI_OFS = ETHERNET_SZ + IP_SZ + UDP_SZ; + if(P25CAI_OFS < hdr.caplen) { + const size_t FRAME_SZ = hdr.caplen - P25CAI_OFS; + // push some zero symbols to separate frames + const size_t SILENCE_SYMS = 48; + symbols_.resize(symbols_.size() + SILENCE_SYMS, 0); + // push symbols from frame payload MSB first + symbols_.reserve(symbols_.capacity() + ((hdr.caplen - P25CAI_OFS) * 4)); + for(size_t i = 0; i < FRAME_SZ; ++i) { + for(int16_t j = 6; j >= 0; j -= 2) { + dibit d = (octets[P25CAI_OFS + i] >> j) & 0x3; + symbols_.push_back(d); + } } } - prev_ = hdr; - prev_is_present_ = true; - } else { - pcap_close(pcap_); - pcap_ = NULL; - if(repeat_) { - // re-open the file - char err[PCAP_ERRBUF_SIZE]; - pcap_ = pcap_open_offline(path_.c_str(), err); - prev_is_present_ = false; - } } + pcap_close(pcap); + } else { + cerr << "error: failed to open " << path; + cerr << " (" << err << ")" << endl; + exit(EXIT_FAILURE); } - return n; } diff --git a/decoder/src/lib/op25_pcap_source_b.h b/decoder/src/lib/op25_pcap_source_b.h index 093f372..96da5a3 100644 --- a/decoder/src/lib/op25_pcap_source_b.h +++ b/decoder/src/lib/op25_pcap_source_b.h @@ -24,18 +24,15 @@ #ifndef INCLUDED_OP25_PCAP_SOURCE_B_H #define INCLUDED_OP25_PCAP_SOURCE_B_H - #include #include -#define PCAP_DONT_INCLUDE_PCAP_BPF_H -#include #include #include -#include +#include typedef boost::shared_ptr op25_pcap_source_b_sptr; -op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay, bool repeat); +op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay); /** * op25_pcap_source_b is a GNU Radio block for reading from a @@ -64,89 +61,39 @@ private: * * \param path The path to the tcpdump-formatted input file. * \param delay The number of seconds to delay before sending the first frame. - * \param repeat Loop back to beginning when EOF is encountered. */ - friend op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay, bool repeat); + friend op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay); /** * op25_pcap_source_b protected constructor. * * \param path The path to the tcpdump-formatted input file. * \param delay The number of seconds to delay before sending the first frame. - * \param repeat Loop back to beginning when EOF is encountered. */ - op25_pcap_source_b(const char *path, float delay, bool repeat); - - /** - * Compute the interframe space between the frames NOW and PREV and - * taking care to ignore HEADER_SZ octets of the frame length. The - * timestamps are presumed to be taken at the end of the frame. - * - * \param NOW The pcap_pkthdr for the most recent frame. - * \param PREV The pcap_pkthdr for the previous frame. - * \param HEADER_SZ The number of octets in the packet header. - * \return The interframe space expressed in seconds. - */ - float ifs(const struct pcap_pkthdr& NOW, const struct pcap_pkthdr& PREV, const size_t HEADER_SZ) const; - - /** - * Read at least NYSMS_REQD symbols from the tcpdump-formatted - * file. This method populates the symbols_ queue and may return - * less than NSYMS_REQD when at end-of-file. When there is no more - * data it returns zero. - * - * \param nsyms_reqd The number of symbols required. - * \return The actual number of symbols read. - */ - uint_least32_t read_at_least(size_t nsyms_reqd); + op25_pcap_source_b(const char *path, float delay); private: - /** - * Path to the pcap file. - */ - std::string path_; - - /** - * Delay (in seconds) before injecting first frame. - */ - const float DELAY_; - - /** - * Repeat the stream when at end? - */ - bool repeat_; - - /** - * Handle to the pcap file. - */ - pcap_t *pcap_; - - /** - * Details for previous frame. - */ - struct pcap_pkthdr prev_; - - /** - * Is prev_ present? - */ - bool prev_is_present_; - /** * Define dibit type */ typedef uint8_t dibit; - /** - * Queue of dibit symbols. - */ - std::deque symbols_; + /** + * The next symbol to be read from the input file. + */ + size_t loc_; /** * The number of symbols/s produced by this block. */ const float SYMBOLS_PER_SEC_; + /** + * Symbols from the input file. + */ + std::vector symbols_; + }; #endif /* INCLUDED_OP25_PCAP_SOURCE_B_H */