GNU Radio Manual and C++ API Reference 3.10.5.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
15#include <gnuradio/logger.h>
16#include <pmt/pmt.h>
17
18namespace gr {
19namespace 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{
113public:
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
179protected:
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:225
std::shared_ptr< pmt_base > pmt_t
typedef for shared pointer (transparent reference counting).
Definition: pmt.h:83