BinaryTokenizer.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 24 SBuf */
10
11#include "squid.h"
12#include "base/Raw.h"
13#include "ip/Address.h"
15
17{
18}
19
20Parser::BinaryTokenizer::BinaryTokenizer(const SBuf &data, const bool expectMore):
21 context(nullptr),
22 data_(data),
23 parsed_(0),
24 syncPoint_(0),
25 expectMore_(expectMore)
26{
27}
28
29static inline
30std::ostream &
31operator <<(std::ostream &os, const Parser::BinaryTokenizerContext *context)
32{
33 if (context)
34 os << context->parent << context->name;
35 return os;
36}
37
39#define BinaryTokenizer_tail(size, start) \
40 " occupying " << (size) << " bytes @" << (start) << " in " << this << \
41 (expectMore_ ? ';' : '.');
42
44void
45Parser::BinaryTokenizer::want(uint64_t size, const char *description) const
46{
47 if (parsed_ + size > data_.length()) {
48 debugs(24, 5, (parsed_ + size - data_.length()) << " more bytes for " <<
49 context << description << BinaryTokenizer_tail(size, parsed_));
50 Must(expectMore_); // throw an error on premature input termination
51 throw InsufficientInput();
52 }
53}
54
55void
56Parser::BinaryTokenizer::got(uint64_t size, const char *description) const
57{
58 debugs(24, 7, context << description <<
59 BinaryTokenizer_tail(size, parsed_ - size));
60}
61
63void
64Parser::BinaryTokenizer::got(uint32_t value, uint64_t size, const char *description) const
65{
66 debugs(24, 7, context << description << '=' << value <<
67 BinaryTokenizer_tail(size, parsed_ - size));
68}
69
71void
72Parser::BinaryTokenizer::got(const SBuf &value, uint64_t size, const char *description) const
73{
74 debugs(24, 7, context << description << '=' <<
75 Raw(nullptr, value.rawContent(), value.length()).hex() <<
76 BinaryTokenizer_tail(size, parsed_ - size));
77
78}
79
81void
82Parser::BinaryTokenizer::got(const Ip::Address &value, uint64_t size, const char *description) const
83{
84 debugs(24, 7, context << description << '=' << value <<
85 BinaryTokenizer_tail(size, parsed_ - size));
86}
87
89void
90Parser::BinaryTokenizer::skipped(uint64_t size, const char *description) const
91{
92 debugs(24, 7, context << description << BinaryTokenizer_tail(size, parsed_ - size));
93
94}
95
99uint32_t
101{
102 // While char may be signed, we view data characters as unsigned,
103 // which helps to arrive at the right 32-bit return value.
104 return static_cast<uint8_t>(data_[parsed_++]);
105}
106
107void
108Parser::BinaryTokenizer::reset(const SBuf &data, const bool expectMore)
109{
110 *this = BinaryTokenizer(data, expectMore);
111}
112
113void
115{
116 parsed_ = syncPoint_;
117}
118
119void
121{
122 syncPoint_ = parsed_;
123}
124
125bool
127{
128 return parsed_ >= data_.length();
129}
130
131uint8_t
132Parser::BinaryTokenizer::uint8(const char *description)
133{
134 want(1, description);
135 const uint8_t result = octet();
136 got(result, 1, description);
137 return result;
138}
139
140uint16_t
141Parser::BinaryTokenizer::uint16(const char *description)
142{
143 want(2, description);
144 const uint16_t result = (octet() << 8) | octet();
145 got(result, 2, description);
146 return result;
147}
148
149uint32_t
150Parser::BinaryTokenizer::uint24(const char *description)
151{
152 want(3, description);
153 const uint32_t result = (octet() << 16) | (octet() << 8) | octet();
154 got(result, 3, description);
155 return result;
156}
157
158uint32_t
159Parser::BinaryTokenizer::uint32(const char *description)
160{
161 want(4, description);
162 const uint32_t result = (octet() << 24) | (octet() << 16) | (octet() << 8) | octet();
163 got(result, 4, description);
164 return result;
165}
166
167SBuf
168Parser::BinaryTokenizer::area(uint64_t size, const char *description)
169{
170 want(size, description);
171 const SBuf result = data_.substr(parsed_, size);
172 parsed_ += size;
173 got(result, size, description);
174 return result;
175}
176
177template <class InAddr>
179Parser::BinaryTokenizer::inetAny(const char *description)
180{
181 InAddr addr;
182 const auto size = sizeof(addr);
183 want(size, description);
184 memcpy(&addr, data_.rawContent() + parsed_, size);
185 parsed_ += size;
186 const Ip::Address result(addr);
187 got(result, size, description);
188 return result;
189}
190
192Parser::BinaryTokenizer::inet4(const char *description)
193{
194 return inetAny<struct in_addr>(description);
195}
196
198Parser::BinaryTokenizer::inet6(const char *description)
199{
200 return inetAny<struct in6_addr>(description);
201}
202
203void
204Parser::BinaryTokenizer::skip(uint64_t size, const char *description)
205{
206 want(size, description);
207 parsed_ += size;
208 skipped(size, description);
209}
210
211/*
212 * BinaryTokenizer::pstringN() implementations below reduce debugging noise by
213 * not parsing empty areas and not summarizing parsing context.success().
214 */
215
216SBuf
217Parser::BinaryTokenizer::pstring8(const char *description)
218{
219 BinaryTokenizerContext pstring(*this, description);
220 if (const uint8_t length = uint8(".length"))
221 return area(length, ".octets");
222 return SBuf();
223}
224
225SBuf
227{
228 BinaryTokenizerContext pstring(*this, description);
229 if (const uint16_t length = uint16(".length"))
230 return area(length, ".octets");
231 return SBuf();
232}
233
234SBuf
236{
237 BinaryTokenizerContext pstring(*this, description);
238 if (const uint32_t length = uint24(".length"))
239 return area(length, ".octets");
240 return SBuf();
241}
242
#define BinaryTokenizer_tail(size, start)
debugging helper that prints a "standard" debugs() trailer
static std::ostream & operator<<(std::ostream &os, const Parser::BinaryTokenizerContext *context)
int size
Definition: ModDevPoll.cc:75
#define Must(condition)
Definition: TextException.h:75
enables efficient debugging with concise field names: Hello.version.major
const char *const name
this context description or nullptr
const BinaryTokenizerContext *const parent
enclosing context or nullptr
SBuf area(uint64_t size, const char *description)
parse size consecutive bytes as an opaque blob
Ip::Address inet4(const char *description)
interpret the next 4 bytes as a raw in_addr structure
void got(uint64_t size, const char *description) const
debugging helper for parsed multi-field structures
SBuf pstring8(const char *description)
up to 255 byte-long p-string
void commit()
make progress: future parsing failures will not rollback beyond this point
bool atEnd() const
no more bytes to parse or skip
void skip(uint64_t size, const char *description)
ignore the next size bytes
void reset(const SBuf &data, const bool expectMore)
uint32_t uint32(const char *description)
parse a four-byte unsigned integer
uint32_t uint24(const char *description)
parse a three-byte unsigned integer (returned as uint32_t)
void want(uint64_t size, const char *description) const
logs and throws if fewer than size octets remain; no other side effects
uint16_t uint16(const char *description)
parse a two-byte unsigned integer
void rollback()
resume [incremental] parsing from the last commit point
Ip::Address inet6(const char *description)
interpret the next 16 bytes as a raw in6_addr structure
uint8_t uint8(const char *description)
parse a single-byte unsigned integer
void skipped(uint64_t size, const char *description) const
debugging helper for skipped fields
Ip::Address inetAny(const char *description)
SBuf pstring16(const char *description)
up to 64 KiB-long p-string
SBuf pstring24(const char *description)
up to 16 MiB-long p-string!
thrown by modern "incremental" parsers when they need more data
Definition: forward.h:18
Definition: Raw.h:21
Raw & hex()
print data using two hex digits per byte (decoder: xxd -r -p)
Definition: Raw.h:30
Definition: SBuf.h:94
const char * rawContent() const
Definition: SBuf.cc:509
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:415
SBuf substr(size_type pos, size_type n=npos) const
Definition: SBuf.cc:576
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
unsigned short uint16
Definition: rfcnb-priv.h:38

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors