BinaryTokenizer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 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 "ip/Address.h"
13 #include "parser/BinaryTokenizer.h"
14 
16 {
17 }
18 
19 Parser::BinaryTokenizer::BinaryTokenizer(const SBuf &data, const bool expectMore):
20  context(nullptr),
21  data_(data),
22  parsed_(0),
23  syncPoint_(0),
24  expectMore_(expectMore)
25 {
26 }
27 
28 static inline
29 std::ostream &
31 {
32  if (context)
33  os << context->parent << context->name;
34  return os;
35 }
36 
38 #define BinaryTokenizer_tail(size, start) \
39  " occupying " << (size) << " bytes @" << (start) << " in " << this << \
40  (expectMore_ ? ';' : '.');
41 
43 void
44 Parser::BinaryTokenizer::want(uint64_t size, const char *description) const
45 {
46  if (parsed_ + size > data_.length()) {
47  debugs(24, 5, (parsed_ + size - data_.length()) << " more bytes for " <<
48  context << description << BinaryTokenizer_tail(size, parsed_));
49  Must(expectMore_); // throw an error on premature input termination
50  throw InsufficientInput();
51  }
52 }
53 
54 void
55 Parser::BinaryTokenizer::got(uint64_t size, const char *description) const
56 {
57  debugs(24, 7, context << description <<
58  BinaryTokenizer_tail(size, parsed_ - size));
59 }
60 
62 void
63 Parser::BinaryTokenizer::got(uint32_t value, uint64_t size, const char *description) const
64 {
65  debugs(24, 7, context << description << '=' << value <<
66  BinaryTokenizer_tail(size, parsed_ - size));
67 }
68 
70 void
71 Parser::BinaryTokenizer::got(const SBuf &value, uint64_t size, const char *description) const
72 {
73  debugs(24, 7, context << description << '=' <<
74  Raw(nullptr, value.rawContent(), value.length()).hex() <<
75  BinaryTokenizer_tail(size, parsed_ - size));
76 
77 }
78 
80 void
81 Parser::BinaryTokenizer::got(const Ip::Address &value, uint64_t size, const char *description) const
82 {
83  debugs(24, 7, context << description << '=' << value <<
84  BinaryTokenizer_tail(size, parsed_ - size));
85 }
86 
88 void
89 Parser::BinaryTokenizer::skipped(uint64_t size, const char *description) const
90 {
91  debugs(24, 7, context << description << BinaryTokenizer_tail(size, parsed_ - size));
92 
93 }
94 
98 uint32_t
100 {
101  // While char may be signed, we view data characters as unsigned,
102  // which helps to arrive at the right 32-bit return value.
103  return static_cast<uint8_t>(data_[parsed_++]);
104 }
105 
106 void
107 Parser::BinaryTokenizer::reset(const SBuf &data, const bool expectMore)
108 {
109  *this = BinaryTokenizer(data, expectMore);
110 }
111 
112 void
114 {
116 }
117 
118 void
120 {
122 }
123 
124 bool
126 {
127  return parsed_ >= data_.length();
128 }
129 
130 uint8_t
131 Parser::BinaryTokenizer::uint8(const char *description)
132 {
133  want(1, description);
134  const uint8_t result = octet();
135  got(result, 1, description);
136  return result;
137 }
138 
139 uint16_t
140 Parser::BinaryTokenizer::uint16(const char *description)
141 {
142  want(2, description);
143  const uint16_t result = (octet() << 8) | octet();
144  got(result, 2, description);
145  return result;
146 }
147 
148 uint32_t
149 Parser::BinaryTokenizer::uint24(const char *description)
150 {
151  want(3, description);
152  const uint32_t result = (octet() << 16) | (octet() << 8) | octet();
153  got(result, 3, description);
154  return result;
155 }
156 
157 uint32_t
158 Parser::BinaryTokenizer::uint32(const char *description)
159 {
160  want(4, description);
161  const uint32_t result = (octet() << 24) | (octet() << 16) | (octet() << 8) | octet();
162  got(result, 4, description);
163  return result;
164 }
165 
166 SBuf
167 Parser::BinaryTokenizer::area(uint64_t size, const char *description)
168 {
169  want(size, description);
170  const SBuf result = data_.substr(parsed_, size);
171  parsed_ += size;
172  got(result, size, description);
173  return result;
174 }
175 
176 template <class InAddr>
178 Parser::BinaryTokenizer::inetAny(const char *description)
179 {
180  InAddr addr;
181  const auto size = sizeof(addr);
182  want(size, description);
183  memcpy(&addr, data_.rawContent() + parsed_, size);
184  parsed_ += size;
185  const Ip::Address result(addr);
186  got(result, size, description);
187  return result;
188 }
189 
191 Parser::BinaryTokenizer::inet4(const char *description)
192 {
193  return inetAny<struct in_addr>(description);
194 }
195 
197 Parser::BinaryTokenizer::inet6(const char *description)
198 {
199  return inetAny<struct in6_addr>(description);
200 }
201 
202 void
203 Parser::BinaryTokenizer::skip(uint64_t size, const char *description)
204 {
205  want(size, description);
206  parsed_ += size;
207  skipped(size, description);
208 }
209 
210 /*
211  * BinaryTokenizer::pstringN() implementations below reduce debugging noise by
212  * not parsing empty areas and not summarizing parsing context.success().
213  */
214 
215 SBuf
216 Parser::BinaryTokenizer::pstring8(const char *description)
217 {
218  BinaryTokenizerContext pstring(*this, description);
219  if (const uint8_t length = uint8(".length"))
220  return area(length, ".octets");
221  return SBuf();
222 }
223 
224 SBuf
225 Parser::BinaryTokenizer::pstring16(const char *description)
226 {
227  BinaryTokenizerContext pstring(*this, description);
228  if (const uint16_t length = uint16(".length"))
229  return area(length, ".octets");
230  return SBuf();
231 }
232 
233 SBuf
234 Parser::BinaryTokenizer::pstring24(const char *description)
235 {
236  BinaryTokenizerContext pstring(*this, description);
237  if (const uint32_t length = uint24(".length"))
238  return area(length, ".octets");
239  return SBuf();
240 }
241 
uint64_t syncPoint_
where to re-start the next parsing attempt
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:404
bool expectMore_
whether more data bytes may arrive in the future
static std::ostream & operator<<(std::ostream &os, const Parser::BinaryTokenizerContext *context)
const char *const name
this context description or nullptr
uint16_t uint16(const char *description)
parse a two-byte unsigned integer
void reset(const SBuf &data, const bool expectMore)
void skipped(uint64_t size, const char *description) const
debugging helper for skipped fields
Definition: SBuf.h:86
Ip::Address inet6(const char *description)
interpret the next 16 bytes as a raw in6_addr structure
#define BinaryTokenizer_tail(size, start)
debugging helper that prints a "standard" debugs() trailer
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
void want(uint64_t size, const char *description) const
logs and throws if fewer than size octets remain; no other side effects
uint64_t parsed_
number of data bytes parsed or skipped
::Parser::InsufficientInput InsufficientInput
const BinaryTokenizerContext * context
debugging: thing being parsed
void const char HLPCB void * data
Definition: stub_helper.cc:16
SBuf pstring8(const char *description)
up to 255 byte-long p-string
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
bool atEnd() const
no more bytes to parse or skip
SBuf area(uint64_t size, const char *description)
parse size consecutive bytes as an opaque blob
SBuf pstring24(const char *description)
up to 16 MiB-long p-string!
uint32_t uint24(const char *description)
parse a three-byte unsigned integer (returned as uint32_t)
void commit()
make progress: future parsing failures will not rollback beyond this point
SBuf pstring16(const char *description)
up to 64 KiB-long p-string
void * addr
Definition: membanger.c:46
uint8_t uint8(const char *description)
parse a single-byte unsigned integer
void skip(uint64_t size, const char *description)
ignore the next size bytes
Ip::Address inetAny(const char *description)
SBuf substr(size_type pos, size_type n=npos) const
Definition: SBuf.cc:586
void got(uint64_t size, const char *description) const
debugging helper for parsed multi-field structures
Ip::Address inet4(const char *description)
interpret the next 4 bytes as a raw in_addr structure
enables efficient debugging with concise field names: Hello.version.major
Definition: Debug.h:184
void rollback()
resume [incremental] parsing from the last commit point
uint32_t uint32(const char *description)
parse a four-byte unsigned integer
const BinaryTokenizerContext *const parent
enclosing context or nullptr
int size
Definition: ModDevPoll.cc:77
const char * rawContent() const
Definition: SBuf.cc:519

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors