@@ -31,50 +31,76 @@ namespace uWS {
3131
3232 constexpr uint64_t STATE_HAS_SIZE = 1ull << (sizeof (uint64_t ) * 8 - 1 );// 0x80000000;
3333 constexpr uint64_t STATE_IS_CHUNKED = 1ull << (sizeof (uint64_t ) * 8 - 2 );// 0x40000000;
34- constexpr uint64_t STATE_SIZE_MASK = ~(3ull << (sizeof (uint64_t ) * 8 - 2 ));// 0x3FFFFFFF;
34+ constexpr uint64_t STATE_IS_CHUNKED_EXTENSION = 1ull << (sizeof (uint64_t ) * 8 - 3 );// 0x20000000;
35+ constexpr uint64_t STATE_SIZE_MASK = ~(STATE_HAS_SIZE | STATE_IS_CHUNKED | STATE_IS_CHUNKED_EXTENSION);// 0x3FFFFFFF;
3536 constexpr uint64_t STATE_IS_ERROR = ~0ull ;// 0xFFFFFFFF;
3637 constexpr uint64_t STATE_SIZE_OVERFLOW = 0x0Full << (sizeof (uint64_t ) * 8 - 8 );// 0x0F000000;
3738
3839 inline unsigned int chunkSize (uint64_t state) {
3940 return state & STATE_SIZE_MASK;
4041 }
4142
43+ inline bool isParsingChunkedExtension (uint64_t state) {
44+ return (state & STATE_IS_CHUNKED_EXTENSION) != 0 ;
45+ }
46+
4247 /* Reads hex number until CR or out of data to consume. Updates state. Returns bytes consumed. */
4348 inline void consumeHexNumber (std::string_view &data, uint64_t &state) {
44- /* Consume everything higher than 32 */
45- while (data.length () && data[0 ] > 32 ) {
46-
47- unsigned char digit = (unsigned char )data[0 ];
48- if (digit >= ' a' ) {
49- digit = (unsigned char ) (digit - (' a' - ' :' ));
50- } else if (digit >= ' A' ) {
51- digit = (unsigned char ) (digit - (' A' - ' :' ));
52- }
49+ if (!isParsingChunkedExtension (state)){
50+ /* Consume everything higher than 32 and not ; (extension)*/
51+ while (data.length () && data[0 ] > 32 && data[0 ] != ' ;' ) {
52+
53+ unsigned char digit = (unsigned char )data[0 ];
54+ if (digit >= ' a' ) {
55+ digit = (unsigned char ) (digit - (' a' - ' :' ));
56+ } else if (digit >= ' A' ) {
57+ digit = (unsigned char ) (digit - (' A' - ' :' ));
58+ }
5359
54- unsigned int number = ((unsigned int ) digit - (unsigned int ) ' 0' );
60+ unsigned int number = ((unsigned int ) digit - (unsigned int ) ' 0' );
5561
56- if (number > 16 || (chunkSize (state) & STATE_SIZE_OVERFLOW)) {
57- state = STATE_IS_ERROR;
58- return ;
59- }
62+ if (number > 16 || (chunkSize (state) & STATE_SIZE_OVERFLOW)) {
63+ state = STATE_IS_ERROR;
64+ return ;
65+ }
6066
61- // extract state bits
62- uint64_t bits = /* state &*/ STATE_IS_CHUNKED;
67+ // extract state bits
68+ uint64_t bits = /* state &*/ STATE_IS_CHUNKED;
6369
64- state = (state & STATE_SIZE_MASK) * 16ull + number;
70+ state = (state & STATE_SIZE_MASK) * 16ull + number;
6571
66- state |= bits;
67- data.remove_prefix (1 );
72+ state |= bits;
73+ data.remove_prefix (1 );
74+ }
6875 }
69- if (data.length () >= 2 ) {
70- /* Consume \r\n */
71- if ((data[0 ] != ' \r ' || data[1 ] != ' \n ' )) {
72- state = STATE_IS_ERROR;
73- return ;
76+
77+ auto len = data.length ();
78+ if (len) {
79+ // consume extension
80+ if (data[0 ] == ' ;' || isParsingChunkedExtension (state)) {
81+ // mark that we are parsing chunked extension
82+ state |= STATE_IS_CHUNKED_EXTENSION;
83+ /* we got chunk extension lets remove it*/
84+ while (data.length ()) {
85+ if (data[0 ] == ' \r ' ) {
86+ // we are done parsing extension
87+ state &= ~STATE_IS_CHUNKED_EXTENSION;
88+ break ;
89+ }
90+ data.remove_prefix (1 );
91+ }
92+ }
93+ if (data.length () >= 2 ) {
94+ /* Consume \r\n */
95+ if ((data[0 ] != ' \r ' || data[1 ] != ' \n ' )) {
96+ state = STATE_IS_ERROR;
97+ return ;
98+ }
99+ state += 2 ; // include the two last /r/n
100+ state |= STATE_HAS_SIZE | STATE_IS_CHUNKED;
101+
102+ data.remove_prefix (2 );
74103 }
75- state += 2 ; // include the two last /r/n
76- state |= STATE_HAS_SIZE | STATE_IS_CHUNKED;
77- data.remove_prefix (2 );
78104 }
79105 // short read
80106 }
0 commit comments