RESTinio

ws_parser.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
9#pragma once
10
11#include <restinio/exception.hpp>
12#include <restinio/websocket/message.hpp>
13
14#include <restinio/utils/impl/bitops.hpp>
15
16#include <cstdint>
17#include <vector>
18#include <list>
19#include <stdexcept>
20
21 namespace restinio
22{
23
24 namespace websocket
25{
26
27 namespace basic
28{
29
31 using byte_t = unsigned char;
32
34 using raw_data_t = std::string;
35
36 namespace impl
37{
38
41 constexpr size_t websocket_first_two_bytes_size = 2;
42 constexpr size_t websocket_max_payload_size_without_ext = 125;
43 constexpr size_t websocket_short_ext_payload_length = 2;
44 constexpr size_t websocket_long_ext_payload_length = 8;
45 constexpr size_t websocket_short_ext_len_code = 126;
46 constexpr size_t websocket_long_ext_len_code = 127;
47 constexpr size_t websocket_masking_key_size = 4;
48
49 constexpr byte_t bit_flag_7 = 0x80;
50 constexpr byte_t bit_flag_6 = 0x40;
51 constexpr byte_t bit_flag_5 = 0x20;
52 constexpr byte_t bit_flag_4 = 0x10;
53 constexpr byte_t opcode_mask = 0x0F;
54 constexpr byte_t payload_len_mask = 0x7F;
56
57//
58// message_details_t
59//
60
62 class message_details_t
63{
64 public:
65 message_details_t() = default;
66
67 message_details_t(
68 final_frame_flag_t final_flag,
69 opcode_t opcode,
70 size_t payload_len ) noexcept
71 : m_final_flag{ final_frame == final_flag }
72 , m_opcode{ opcode }
73 {
74 init_payload_len( payload_len );
75 }
76
77 message_details_t(
78 final_frame_flag_t final_flag,
79 opcode_t opcode,
80 size_t payload_len,
81 std::uint32_t masking_key )
82 : m_final_flag{ final_frame == final_flag }
83 , m_opcode{ opcode }
84 , m_mask_flag( true )
85 , m_masking_key( masking_key )
86 {
87 init_payload_len( payload_len );
88 }
89
91 std::uint64_t
92 payload_len() const
93 {
94 // 126 and 127 are codes of ext payload. 125 and lower are real payload len.
95 return m_payload_len > websocket_max_payload_size_without_ext? m_ext_payload_len: m_payload_len;
96 }
97
99 void
100 set_masking_key( std::uint32_t value )
101 {
102 m_masking_key = value;
103 m_mask_flag = true;
104 }
105
107 bool m_final_flag = true;
108
111 bool m_rsv1_flag = false;
112 bool m_rsv2_flag = false;
113 bool m_rsv3_flag = false;
115
117 opcode_t m_opcode = opcode_t::continuation_frame;
118
120 bool m_mask_flag = false;
121
123
126 std::uint8_t m_payload_len = 0;
127
129 std::uint64_t m_ext_payload_len = 0;
130
132 std::uint32_t m_masking_key = 0;
133
134 private:
135
137
141 void
142 init_payload_len( size_t payload_len )
143 {
144 if( payload_len > websocket_max_payload_size_without_ext )
145 {
146 // if payload greater than 2bytes-number.
147 m_payload_len = payload_len > 0xFFFF ?
148 websocket_long_ext_len_code:
149 websocket_short_ext_len_code;
150
151 m_ext_payload_len = payload_len;
152 }
153 else
154 {
155 m_payload_len = static_cast< std::uint8_t >( payload_len );
156 }
157 }
158};
159
160//
161// expected_data_t
162//
163
165 struct expected_data_t
166{
167 expected_data_t() = default;
168
169 expected_data_t( size_t expected_size )
170 : m_expected_size{ expected_size }
171 {
172 m_loaded_data.reserve( m_expected_size );
173 }
174
176 size_t m_expected_size{0};
177
179 raw_data_t m_loaded_data;
180
182 bool
183 all_bytes_loaded() const
184 {
185 return m_loaded_data.size() == m_expected_size;
186 }
187
189
193 bool
194 add_byte_and_check_size( byte_t byte )
195 {
196 if( m_loaded_data.size() == m_expected_size )
197 throw exception_t("Cannot add one more bytes to expected data.");
198
199 m_loaded_data.push_back(static_cast<raw_data_t::value_type>(byte));
200
201 return all_bytes_loaded();
202 }
203
205 void
206 reset( size_t expected_size )
207 {
208 m_expected_size = expected_size;
209 m_loaded_data.clear();
210 m_loaded_data.reserve( expected_size );
211 }
212};
213
214//
215// read_number_from_big_endian_bytes
216//
217
219 template <typename T>
220 inline void
221 read_number_from_big_endian_bytes( T & number, const raw_data_t & data )
222{
223 number = T{};
224 for( const auto byte: data )
225 {
226 number <<= 8;
227 number |= static_cast<std::uint8_t>( byte );
228 }
229}
230
231//
232// write_number_to_big_endian_bytes
233//
234
236 template <int Bytes>
237 inline void
238 write_number_to_big_endian_bytes( std::uint64_t& number, raw_data_t & data )
239{
240 for( auto i = 0 ; i < Bytes ; ++i )
241 {
242 auto shift_value = (Bytes - i - 1) * 8;
243 data.push_back( static_cast<raw_data_t::value_type>(
244 (number >> shift_value) & 0xFF) );
245 }
246}
247
248//
249// ws_parser_t
250//
251
253
259 class ws_parser_t
260{
261 public:
262
264 size_t
265 parser_execute( const char * data, size_t size )
266 {
267 size_t parsed_bytes = 0;
268
269 while( parsed_bytes < size &&
270 m_current_state != state_t::header_parsed )
271 {
272 byte_t byte = static_cast< byte_t >( data[parsed_bytes] );
273
274 process_byte( byte );
275
276 parsed_bytes++;
277 }
278
279 return parsed_bytes;
280 }
281
283 bool
284 header_parsed() const
285 {
286 return m_current_state == state_t::header_parsed;
287 }
288
290
293 void
294 reset()
295 {
296 m_current_state = state_t::waiting_for_first_2_bytes;
297 m_current_msg = message_details_t();
298 m_expected_data.reset( websocket_first_two_bytes_size );
299 }
300
302 const message_details_t &
303 current_message() const
304 {
305 return m_current_msg;
306 }
307
308 private:
309
311
314 expected_data_t m_expected_data{ websocket_first_two_bytes_size };
315
317 message_details_t m_current_msg;
318
320 enum class state_t
321 {
322 waiting_for_first_2_bytes,
323 waiting_for_ext_len,
324 waiting_for_mask_key,
325 header_parsed
326 };
327
329 state_t m_current_state = state_t::waiting_for_first_2_bytes;
330
332 void
333 process_byte( byte_t byte )
334 {
335 if( m_expected_data.add_byte_and_check_size(byte) )
336 {
337 switch( m_current_state )
338 {
339
340 case state_t::waiting_for_first_2_bytes:
341
342 process_first_2_bytes();
343 break;
344
345 case state_t::waiting_for_ext_len:
346
347 process_extended_length();
348 break;
349
350 case state_t::waiting_for_mask_key:
351
352 process_masking_key();
353 break;
354
355 case state_t::header_parsed:
356
357 break;
358 }
359 }
360 }
361
363
366 void
367 process_first_2_bytes()
368 {
369 parse_first_2_bytes(
370 m_expected_data.m_loaded_data );
371
372 size_t payload_len = m_current_msg.m_payload_len;
373
374 if( payload_len > websocket_max_payload_size_without_ext )
375 {
376 size_t expected_data_size = payload_len == websocket_short_ext_len_code?
377 websocket_short_ext_payload_length:
378 websocket_long_ext_payload_length;
379
380 m_expected_data.reset( expected_data_size );
381
382 m_current_state = state_t::waiting_for_ext_len;
383 }
384 else if( m_current_msg.m_mask_flag )
385 {
386 size_t expected_data_size = websocket_masking_key_size;
387 m_expected_data.reset( expected_data_size );
388
389 m_current_state = state_t::waiting_for_mask_key;
390 }
391 else
392 {
393 size_t expected_data_size = payload_len;
394 m_expected_data.reset( expected_data_size );
395
396 m_current_state = state_t::header_parsed;
397 }
398 }
399
401
404 void
405 process_extended_length()
406 {
407 parse_ext_payload_len(
408 m_current_msg.m_payload_len,
409 m_expected_data.m_loaded_data );
410
411 if( m_current_msg.m_mask_flag )
412 {
413 size_t expected_data_size = websocket_masking_key_size;
414 m_expected_data.reset( expected_data_size );
415
416 m_current_state = state_t::waiting_for_mask_key;
417 }
418 else
419 {
420 m_current_state = state_t::header_parsed;
421 }
422 }
423
424 void
426
429 process_masking_key()
430 {
431 parse_masking_key(
432 m_current_msg.m_mask_flag,
433 m_expected_data.m_loaded_data );
434
435 m_current_state = state_t::header_parsed;
436 }
437
439 void
440 parse_first_2_bytes(
441 const raw_data_t & data )
442 {
443 m_current_msg.m_final_flag = (data[0] & bit_flag_7) != 0;
444 m_current_msg.m_rsv1_flag = (data[0] & bit_flag_6) != 0;
445 m_current_msg.m_rsv2_flag = (data[0] & bit_flag_5) != 0;
446 m_current_msg.m_rsv3_flag = (data[0] & bit_flag_4) != 0;
447
448 m_current_msg.m_opcode = static_cast< opcode_t >( data[0] & opcode_mask );
449
450 m_current_msg.m_mask_flag = (data[1] & bit_flag_7) != 0;
451 m_current_msg.m_payload_len = data[1] & payload_len_mask;
452 }
453
455 void
456 parse_ext_payload_len(
457 std::uint8_t payload_len,
458 const raw_data_t & data )
459 {
460 if( payload_len == websocket_short_ext_len_code )
461 {
462 read_number_from_big_endian_bytes(
463 m_current_msg.m_ext_payload_len, data );
464 }
465 else if( payload_len == websocket_long_ext_len_code )
466 {
467 read_number_from_big_endian_bytes(
468 m_current_msg.m_ext_payload_len, data );
469 }
470 }
471
473 void
474 parse_masking_key(
475 bool mask_flag,
476 const raw_data_t & data )
477 {
478 if( mask_flag )
479 {
480 read_number_from_big_endian_bytes(
481 m_current_msg.m_masking_key, data );
482 }
483 }
484};
485
487 inline void
488 mask_unmask_payload( std::uint32_t masking_key, raw_data_t & payload )
489{
490 using namespace ::restinio::utils::impl::bitops;
491
492 const std::size_t MASK_SIZE = 4;
493 const uint8_t mask[ MASK_SIZE ] = {
494 n_bits_from< std::uint8_t, 24 >(masking_key),
495 n_bits_from< std::uint8_t, 16 >(masking_key),
496 n_bits_from< std::uint8_t, 8 >(masking_key),
497 n_bits_from< std::uint8_t, 0 >(masking_key),
498 };
499
500 const auto payload_size = payload.size();
501 for( std::size_t i = 0; i < payload_size; )
502 {
503 for( std::size_t j = 0; j < MASK_SIZE && i < payload_size; ++j, ++i )
504 {
505 payload[ i ] ^= mask[ j ];
506 }
507 }
508}
509
511
514 inline raw_data_t
515 write_message_details( const message_details_t & message )
516{
517 raw_data_t result;
518
519 byte_t byte = 0x00;
520
521 if( message.m_final_flag ) byte |= bit_flag_7;
522 if( message.m_rsv1_flag ) byte |= bit_flag_6;
523 if( message.m_rsv2_flag ) byte |= bit_flag_5;
524 if( message.m_rsv3_flag ) byte |= bit_flag_4;
525
526 byte |= static_cast< std::uint8_t> (message.m_opcode) & opcode_mask;
527
528 result.push_back( static_cast<raw_data_t::value_type>(byte) );
529
530 byte = 0x00;
531
532 if( message.m_mask_flag )
533 byte |= bit_flag_7;
534
535 auto length = message.m_payload_len;
536
537 if( length < websocket_short_ext_len_code )
538 {
539 byte |= length;
540 result.push_back( static_cast<raw_data_t::value_type>(byte) );
541 }
542 else if ( length == websocket_short_ext_len_code )
543 {
544 byte |= websocket_short_ext_len_code;
545
546 result.push_back( static_cast<raw_data_t::value_type>(byte) );
547
548 auto ext_len = message.m_ext_payload_len;
549
550 write_number_to_big_endian_bytes< websocket_short_ext_payload_length>(
551 ext_len, result );
552 }
553 else if ( length == websocket_long_ext_len_code )
554 {
555 byte |= websocket_long_ext_len_code;
556
557 result.push_back( static_cast<raw_data_t::value_type>(byte) );
558
559 auto ext_len = message.m_ext_payload_len;
560
561 write_number_to_big_endian_bytes< websocket_long_ext_payload_length >(
562 ext_len, result );
563 }
564
565 if( message.m_mask_flag )
566 {
567 using namespace ::restinio::utils::impl::bitops;
568
569 using ch_type = raw_data_t::value_type;
570
571 const auto key = message.m_masking_key;
572 result.push_back( n_bits_from< ch_type, 24 >(key) );
573 result.push_back( n_bits_from< ch_type, 16 >(key) );
574 result.push_back( n_bits_from< ch_type, 8 >(key) );
575 result.push_back( n_bits_from< ch_type, 0 >(key) );
576 }
577
578 return result;
579}
580
582
585 inline raw_data_t
586 write_message_details(
587 final_frame_flag_t final_flag,
588 opcode_t opcode,
589 size_t payload_len )
590{
591 return write_message_details(
592 message_details_t{ final_flag, opcode, payload_len } );
593}
594
596
599 inline raw_data_t
600 write_message_details(
601 final_frame_flag_t final_flag,
602 opcode_t opcode,
603 size_t payload_len,
604 std::uint32_t masking_key )
605{
606 return write_message_details(
607 message_details_t{ final_flag, opcode, payload_len, masking_key } );
608}
609
610} /* namespace impl */
611
612} /* namespace basic */
613
614} /* namespace websocket */
615
616} /* namespace restinio */
bitops.hpp
restinio::exception_t
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
restinio::websocket::basic::impl::message_details_t
Websocket message class with more detailed protocol information.
Definition: ws_parser.hpp:63
restinio::websocket::basic::impl::message_details_t::m_rsv2_flag
bool m_rsv2_flag
Definition: ws_parser.hpp:112
restinio::websocket::basic::impl::message_details_t::payload_len
std::uint64_t payload_len() const
Get payload len.
Definition: ws_parser.hpp:92
restinio::websocket::basic::impl::message_details_t::m_rsv1_flag
bool m_rsv1_flag
Reserved flags.
Definition: ws_parser.hpp:111
restinio::websocket::basic::impl::message_details_t::message_details_t
message_details_t()=default
restinio::websocket::basic::impl::message_details_t::m_rsv3_flag
bool m_rsv3_flag
Definition: ws_parser.hpp:113
restinio::websocket::basic::impl::message_details_t::m_masking_key
std::uint32_t m_masking_key
Masking key.
Definition: ws_parser.hpp:132
restinio::websocket::basic::impl::message_details_t::m_payload_len
std::uint8_t m_payload_len
Payload len.
Definition: ws_parser.hpp:126
restinio::websocket::basic::impl::message_details_t::message_details_t
message_details_t(final_frame_flag_t final_flag, opcode_t opcode, size_t payload_len, std::uint32_t masking_key)
Definition: ws_parser.hpp:77
restinio::websocket::basic::impl::message_details_t::m_ext_payload_len
std::uint64_t m_ext_payload_len
Ext payload len.
Definition: ws_parser.hpp:129
restinio::websocket::basic::impl::message_details_t::m_final_flag
bool m_final_flag
Final flag.
Definition: ws_parser.hpp:107
restinio::websocket::basic::impl::message_details_t::message_details_t
message_details_t(final_frame_flag_t final_flag, opcode_t opcode, size_t payload_len) noexcept
Definition: ws_parser.hpp:67
restinio::websocket::basic::impl::message_details_t::init_payload_len
void init_payload_len(size_t payload_len)
Initialize payload len.
Definition: ws_parser.hpp:142
restinio::websocket::basic::impl::message_details_t::m_mask_flag
bool m_mask_flag
Mask flag.
Definition: ws_parser.hpp:120
restinio::websocket::basic::impl::message_details_t::set_masking_key
void set_masking_key(std::uint32_t value)
Set masking key.
Definition: ws_parser.hpp:100
restinio::websocket::basic::impl::message_details_t::m_opcode
opcode_t m_opcode
Opcode.
Definition: ws_parser.hpp:117
restinio::websocket::basic::impl::ws_parser_t
Websocket parser.
Definition: ws_parser.hpp:260
restinio::websocket::basic::impl::ws_parser_t::process_extended_length
void process_extended_length()
Process extended length.
Definition: ws_parser.hpp:405
restinio::websocket::basic::impl::ws_parser_t::m_current_msg
message_details_t m_current_msg
Current websocket message details.
Definition: ws_parser.hpp:317
restinio::websocket::basic::impl::ws_parser_t::reset
void reset()
Reset internal state.
Definition: ws_parser.hpp:294
restinio::websocket::basic::impl::ws_parser_t::current_message
const message_details_t & current_message() const
Get current mesasge details.
Definition: ws_parser.hpp:303
restinio::websocket::basic::impl::ws_parser_t::process_byte
void process_byte(byte_t byte)
Process one byte of incoming buffer.
Definition: ws_parser.hpp:333
restinio::websocket::basic::impl::ws_parser_t::parse_first_2_bytes
void parse_first_2_bytes(const raw_data_t &data)
Parse first two bytes of message from buffer.
Definition: ws_parser.hpp:440
restinio::websocket::basic::impl::ws_parser_t::parse_ext_payload_len
void parse_ext_payload_len(std::uint8_t payload_len, const raw_data_t &data)
Parse extended length from buffer.
Definition: ws_parser.hpp:456
restinio::websocket::basic::impl::ws_parser_t::parse_masking_key
void parse_masking_key(bool mask_flag, const raw_data_t &data)
Parse masking key from buffer.
Definition: ws_parser.hpp:474
restinio::websocket::basic::impl::ws_parser_t::state_t
state_t
Internal state.
Definition: ws_parser.hpp:321
restinio::websocket::basic::impl::ws_parser_t::state_t::waiting_for_ext_len
@ waiting_for_ext_len
restinio::websocket::basic::impl::ws_parser_t::state_t::waiting_for_first_2_bytes
@ waiting_for_first_2_bytes
restinio::websocket::basic::impl::ws_parser_t::state_t::header_parsed
@ header_parsed
restinio::websocket::basic::impl::ws_parser_t::state_t::waiting_for_mask_key
@ waiting_for_mask_key
restinio::websocket::basic::impl::ws_parser_t::parser_execute
size_t parser_execute(const char *data, size_t size)
Parse piece of data from buffer.
Definition: ws_parser.hpp:265
restinio::websocket::basic::impl::ws_parser_t::process_masking_key
void process_masking_key()
Process extended length.
Definition: ws_parser.hpp:429
restinio::websocket::basic::impl::ws_parser_t::header_parsed
bool header_parsed() const
Check header of current websocket message is parsed.
Definition: ws_parser.hpp:284
restinio::websocket::basic::impl::ws_parser_t::m_current_state
state_t m_current_state
Current state.
Definition: ws_parser.hpp:329
restinio::websocket::basic::impl::ws_parser_t::m_expected_data
expected_data_t m_expected_data
Buffer for parts of websocket message with known size.
Definition: ws_parser.hpp:314
restinio::websocket::basic::impl::ws_parser_t::process_first_2_bytes
void process_first_2_bytes()
Process first two bytes of message.
Definition: ws_parser.hpp:367
exception.hpp
message.hpp
restinio::utils::impl::bitops::details::mask
constexpr T mask(unsigned bits_to_extract)
Definition: bitops.hpp:24
restinio::utils::impl::bitops
Definition: bitops.hpp:19
restinio::utils::sha1::details::byte
unsigned int byte(digest_t::value_type v)
Definition: sha1.hpp:365
restinio::websocket::basic::impl::read_number_from_big_endian_bytes
void read_number_from_big_endian_bytes(T &number, const raw_data_t &data)
Read number from buffer with network bytes order.
Definition: ws_parser.hpp:221
restinio::websocket::basic::impl::mask_unmask_payload
void mask_unmask_payload(std::uint32_t masking_key, raw_data_t &payload)
Do msak/unmask operation with buffer.
Definition: ws_parser.hpp:488
restinio::websocket::basic::impl::bit_flag_7
constexpr byte_t bit_flag_7
Definition: ws_parser.hpp:49
restinio::websocket::basic::impl::websocket_max_payload_size_without_ext
constexpr size_t websocket_max_payload_size_without_ext
Definition: ws_parser.hpp:42
restinio::websocket::basic::impl::websocket_long_ext_payload_length
constexpr size_t websocket_long_ext_payload_length
Definition: ws_parser.hpp:44
restinio::websocket::basic::impl::write_message_details
raw_data_t write_message_details(const message_details_t &message)
Serialize websocket message details into bytes buffer.
Definition: ws_parser.hpp:515
restinio::websocket::basic::impl::websocket_short_ext_len_code
constexpr size_t websocket_short_ext_len_code
Definition: ws_parser.hpp:45
restinio::websocket::basic::impl::bit_flag_5
constexpr byte_t bit_flag_5
Definition: ws_parser.hpp:51
restinio::websocket::basic::impl::payload_len_mask
constexpr byte_t payload_len_mask
Definition: ws_parser.hpp:54
restinio::websocket::basic::impl::bit_flag_4
constexpr byte_t bit_flag_4
Definition: ws_parser.hpp:52
restinio::websocket::basic::impl::websocket_short_ext_payload_length
constexpr size_t websocket_short_ext_payload_length
Definition: ws_parser.hpp:43
restinio::websocket::basic::impl::bit_flag_6
constexpr byte_t bit_flag_6
Definition: ws_parser.hpp:50
restinio::websocket::basic::impl::opcode_mask
constexpr byte_t opcode_mask
Definition: ws_parser.hpp:53
restinio::websocket::basic::impl::websocket_long_ext_len_code
constexpr size_t websocket_long_ext_len_code
Definition: ws_parser.hpp:46
restinio::websocket::basic::impl::websocket_masking_key_size
constexpr size_t websocket_masking_key_size
Definition: ws_parser.hpp:47
restinio::websocket::basic::impl::websocket_first_two_bytes_size
constexpr size_t websocket_first_two_bytes_size
Websocket parser constants.
Definition: ws_parser.hpp:41
restinio::websocket::basic::impl::write_number_to_big_endian_bytes
void write_number_to_big_endian_bytes(std::uint64_t &number, raw_data_t &data)
Save number to buffer with network bytes order.
Definition: ws_parser.hpp:238
restinio::websocket::basic::opcode_t
opcode_t
Definition: message.hpp:37
restinio::websocket::basic::raw_data_t
std::string raw_data_t
Bytes buffer.
Definition: ws_parser.hpp:34
restinio::websocket::basic::byte_t
unsigned char byte_t
Alias for byte.
Definition: ws_parser.hpp:31
restinio::websocket::basic::final_frame
constexpr final_frame_flag_t final_frame
Definition: message.hpp:135
restinio::websocket::basic::final_frame_flag_t
final_frame_flag_t
WS frame (message) "final"/"not final" flag.
Definition: message.hpp:133
restinio
Definition: asio_include.hpp:21
restinio::websocket::basic::impl::expected_data_t
Data with expected size.
Definition: ws_parser.hpp:166
restinio::websocket::basic::impl::expected_data_t::add_byte_and_check_size
bool add_byte_and_check_size(byte_t byte)
Try to add one more byte to loaded data and check loaded data size.
Definition: ws_parser.hpp:194
restinio::websocket::basic::impl::expected_data_t::reset
void reset(size_t expected_size)
Reset internal state on next expected data size.
Definition: ws_parser.hpp:206
restinio::websocket::basic::impl::expected_data_t::all_bytes_loaded
bool all_bytes_loaded() const
Check all bytes are loaded.
Definition: ws_parser.hpp:183
restinio::websocket::basic::impl::expected_data_t::expected_data_t
expected_data_t()=default
restinio::websocket::basic::impl::expected_data_t::expected_data_t
expected_data_t(size_t expected_size)
Definition: ws_parser.hpp:169
restinio::websocket::basic::impl::expected_data_t::m_expected_size
size_t m_expected_size
Expected data size in bytes.
Definition: ws_parser.hpp:176
restinio::websocket::basic::impl::expected_data_t::m_loaded_data
raw_data_t m_loaded_data
Buffer for accumulating data.
Definition: ws_parser.hpp:179