GNU Radio Manual and C++ API Reference  3.10.9.1
The Free & Open Software Radio Ecosystem
header_format_base.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /* Copyright 2016 Free Software Foundation, Inc.
3  *
4  * This file is part of GNU Radio
5  *
6  * SPDX-License-Identifier: GPL-3.0-or-later
7  *
8  */
9 
10 #ifndef INCLUDED_DIGITAL_HEADER_FORMAT_BASE_H
11 #define INCLUDED_DIGITAL_HEADER_FORMAT_BASE_H
12 
13 #include <gnuradio/digital/api.h>
15 #include <gnuradio/logger.h>
16 #include <pmt/pmt.h>
17 
18 namespace gr {
19 namespace digital {
20 
21 /*!
22  * \brief Base header formatter class.
23  * \ingroup packet_operators_blk
24  *
25  * \details
26  *
27  * Creates a base class that other packet formatters will inherit
28  * from. The child classes create and parse protocol-specific
29  * headers. To add a new protocol processing class, create a class
30  * that inherits from this and overload the necessary
31  * functions. The main functions to overload are:
32  *
33  * \li header_format_base::format: takes in a payload and
34  * creates a header from it.
35  *
36  * \li header_format_base::parse: receive bits and extract
37  * the header info. These are expected to be hard bits (0 or 1)
38  * that have either been sliced or gone through an FEC decoder.
39  *
40  * \li header_format_base::header_nbits: the number of bits
41  * in the full header (including an access code).
42  *
43  * \li header_format_base::header_ok: checks to see if the
44  * received header is ok. Since the header often specifies the
45  * length of the frame to decode next, it is important that this
46  * information be correct.
47  *
48  * \li header_format_base::header_payload: unpacks the header
49  * register (from the class header_buffer) as a set of bits into
50  * its component parts of the header. For example, this may find
51  * and extract the frame length field as a 16-bit value and/or
52  * flags related to the type of modulation and FEC codes used in
53  * the frame's payload.
54  *
55  * Protected functions of this class that the child class should
56  * overload include:
57  *
58  * \li enter_search
59  * \li enter_have_sync
60  * \li enter_have_header
61  *
62  * These three function represent the different states of the
63  * parsing state machine. Expected behavior is that the protocol
64  * has some known word that we are first looking for the identify
65  * the start of the frame. The parsing FSM starts in a state to
66  * search for the beginning of the header, normally by looking for
67  * a known word (i.e., the access code). Then it changes state to
68  * read in the full header. We expect that the protocol provides
69  * the length of the header for processing, so the parsing looks
70  * pulls in the full length of the header. Then it changes state
71  * to the "have header" state for checking and processing. The
72  * base class provides the basic functionality for this state
73  * machine. However, most likely, each child class must manage
74  * these states for themselves.
75  *
76  * This class is specifically designed to work with packets/frames
77  * in the asynchronous PDU architecture of GNU Radio. See the
78  * packet_format_async block for formatting the headers onto
79  * payloads and packet_parse_b block for parsing headers in a
80  * receiver.
81  *
82  * The Packet Format block takes in a PDU and uses a formatter
83  * class derived from this class to add a header onto the
84  * packet. The Packet Format blocks takes in the PDU, unpacks the
85  * message, and passes it to a formatter class' format function,
86  * which builds a header based on the payload. The header is
87  * passed back and emitted from formatter block as a separate
88  * output. The async format block, packet_format_async, has two
89  * message output ports. The 'header' port passes the header out
90  * as a PDU and the 'payload' passes the payload out as a PDU. The
91  * flowgraph can then separately modulate and combine these two
92  * pieces in the follow-on processing.
93  *
94  * The packet_sync_b block uses the formatter class by calling the
95  * 'parse' function to parse the received packet headers. This
96  * parser block is a sink for the data stream and emits a message
97  * from an 'info' port that contains an PMT dictionary of the
98  * information in the header. The formatter class determines the
99  * dictionary keys.
100  *
101  * This is the base class for dealing with formatting headers for
102  * different protocols and purposes. For other header formatting
103  * behaviors, create a child class from here and overload the
104  * format, parse, and parsing state machine functions as
105  * necessary.
106  *
107  * \sa header_format_default
108  * \sa header_format_counter
109  */
111  : public std::enable_shared_from_this<gr::digital::header_format_base>
112 {
113 public:
114  typedef std::shared_ptr<header_format_base> sptr;
115 
118 
119  sptr base() { return shared_from_this(); };
120  sptr formatter() { return shared_from_this(); };
121 
122  /*!
123  * Function to creates a header. The child classes overload this
124  * function to format the header in the protocol-specific way.
125  *
126  * \param nbytes_in The length (in bytes) of the \p input payload
127  * \param input An array of unsigned chars of the packet payload
128  * \param output A pmt::u8vector with the new header prepended
129  * onto the input data.
130  * \param info A pmt::dict containing meta data and info about
131  * the PDU (generally from the metadata portion of the
132  * input PDU). Data can be extracted from this for the
133  * header formatting or inserted.
134  *
135  * MUST be overloaded.
136  */
137  virtual bool format(int nbytes_in,
138  const unsigned char* input,
139  pmt::pmt_t& output,
140  pmt::pmt_t& info) = 0;
141 
142  /*!
143  * Parses a header. This function is overloaded in the child
144  * class, which knows how to convert the incoming hard bits (0's
145  * and 1's) back into a packet header.
146  *
147  * \param nbits_in The number of bits in the input array.
148  * \param input The input as hard decision bits.
149  * \param info A vector of pmt::dicts to hold any meta data or
150  * info about the PDU. When parsing the header, the
151  * formatter can add info from the header into this dict.
152  * Each packet has a single PMT dictionary of info, so
153  * the vector length is the number of packets received
154  * extracted during one call to this parser function.
155  * \param nbits_processed Number of input bits actually
156  * processed; If all goes well, this is nbits_in. A
157  * premature return after a bad header could be less than
158  * this.
159  *
160  * MUST be overloaded.
161  */
162  virtual bool parse(int nbits_in,
163  const unsigned char* input,
164  std::vector<pmt::pmt_t>& info,
165  int& nbits_processed) = 0;
166 
167  /*!
168  * Returns the length of the formatted header in bits.
169  * MUST be overloaded.
170  */
171  virtual size_t header_nbits() const = 0;
172 
173  /*!
174  * Returns the length of the formatted header in bytes.
175  * Auto-calculated from the overloaded header_nbits().
176  */
177  size_t header_nbytes() const;
178 
179 protected:
180  enum state_t { STATE_SYNC_SEARCH, STATE_HAVE_SYNC };
181 
182  state_t d_state; //!< state of the state machine
183  header_buffer d_hdr_reg; //!< header_buffer object to hold header bits
184  pmt::pmt_t d_info; //!< info captured from the header
185 
186  //! Enter Search state of the state machine to find the access code.
187  virtual void enter_search();
188 
189  //! Access code found, start getting the header
190  virtual void enter_have_sync();
191 
192  //! Header found, setup for pulling in the hard decision bits
193  virtual void enter_have_header(int payload_len);
194 
195  //! Verify that the header is valid
196  virtual bool header_ok() = 0;
197 
198  /*! Get info from the header; return payload length and package
199  * rest of data in d_info dictionary.
200  */
201  virtual int header_payload() = 0;
202 
203  /*! Used by blocks to access the logger system.
204  */
207 };
208 
209 } // namespace digital
210 } // namespace gr
211 
212 #endif /* INCLUDED_DIGITAL_HEADER_FORMAT_BASE_H */
Helper class for handling payload headers.
Definition: header_buffer.h:154
Base header formatter class.
Definition: header_format_base.h:112
pmt::pmt_t d_info
info captured from the header
Definition: header_format_base.h:184
gr::logger_ptr d_debug_logger
Definition: header_format_base.h:206
virtual bool header_ok()=0
Verify that the header is valid.
gr::logger_ptr d_logger
Definition: header_format_base.h:205
header_buffer d_hdr_reg
header_buffer object to hold header bits
Definition: header_format_base.h:183
virtual size_t header_nbits() const =0
virtual void enter_have_sync()
Access code found, start getting the header.
virtual bool format(int nbytes_in, const unsigned char *input, pmt::pmt_t &output, pmt::pmt_t &info)=0
sptr base()
Definition: header_format_base.h:119
state_t d_state
state of the state machine
Definition: header_format_base.h:182
state_t
Definition: header_format_base.h:180
std::shared_ptr< header_format_base > sptr
Definition: header_format_base.h:114
virtual void enter_have_header(int payload_len)
Header found, setup for pulling in the hard decision bits.
virtual void enter_search()
Enter Search state of the state machine to find the access code.
sptr formatter()
Definition: header_format_base.h:120
virtual bool parse(int nbits_in, const unsigned char *input, std::vector< pmt::pmt_t > &info, int &nbits_processed)=0
#define DIGITAL_API
Definition: gr-digital/include/gnuradio/digital/api.h:18
GNU Radio logging wrapper.
Definition: basic_block.h:29
std::shared_ptr< logger > logger_ptr
Definition: logger.h:250
std::shared_ptr< pmt_base > pmt_t
typedef for shared pointer (transparent reference counting).
Definition: pmt.h:83