11#include "websocket_parser.h"
22#include <assert.h>
3- #include <stddef.h>
4- #include <stdlib.h>
53#include <string.h>
6- #include <limits.h>
74
85
96#ifdef __GNUC__
1411# define UNEXPECTED (X ) (X)
1512#endif
1613
17- #define OPCODE_MASK 0xF
14+ #define SET_STATE (V ) parser->state = V
15+ #define HAS_DATA () (p < end )
16+ #define CC (*p)
17+ #define GET_PARSED () ( (p == end) ? len : (p - data) )
1818
1919#define NOTIFY_CB (FOR ) \
2020do { \
2121 if (settings->on_##FOR) { \
2222 if (settings->on_##FOR(parser) != 0) { \
23- return i; \
23+ return GET_PARSED(); \
2424 } \
2525 } \
2626} while (0)
2929do { \
3030 if (settings->on_##FOR) { \
3131 if (settings->on_##FOR(parser, ptr, len) != 0) { \
32- return i; \
32+ return GET_PARSED(); \
3333 } \
3434 } \
3535} while (0)
@@ -55,114 +55,119 @@ void websocket_parser_settings_init(websocket_parser_settings *settings) {
5555}
5656
5757size_t websocket_parser_execute (websocket_parser * parser , const websocket_parser_settings * settings , const char * data , size_t len ) {
58- size_t i = 0 ;
59- size_t r = 0 ;
60- char c ;
58+ const char * p ;
59+ const char * end = data + len ;
60+ uint8_t header_size = 0 ;
6161
62- while (EXPECTED (i < len )) {
63- c = data [i ];
62+ for (p = data ; p != end ; p ++ ) {
6463 switch (parser -> state ) {
6564 case s_start :
66- parser -> length = 0 ;
67- parser -> flags = ( uint32_t ) ( c & WS_OP_MASK ) ;
68- c >>= 7 ;
69- if (EXPECTED (c & 1 )) {
65+ parser -> length = 0 ;
66+ parser -> mask_offset = 0 ;
67+ parser -> flags = ( uint32_t ) ( CC & WS_OP_MASK ) ;
68+ if (EXPECTED (CC & ( 1 << 7 ) )) {
7069 parser -> flags |= WS_FIN ;
7170 }
72- parser -> state = s_head ;
71+ SET_STATE (s_head );
72+
73+ header_size ++ ;
7374 break ;
7475 case s_head :
75- parser -> length = (size_t )c & 0x7F ;
76- if (c & 0x80 ) {
76+ parser -> length = (size_t )CC & 0x7F ;
77+ if (CC & 0x80 ) {
7778 parser -> flags |= WS_HAS_MASK ;
7879 }
7980 if (EXPECTED (parser -> length >= 126 )) {
8081 if (EXPECTED (parser -> length == 127 )) {
81- if (EXPECTED (len - i > 8 )) {
82- parser -> length = (uint16_t )data [i + 1 ];
83- i += 8 ;
84- } else {
85- parser -> require = 8 ;
86- parser -> state = s_length ;
87- }
82+ parser -> require = 8 ;
8883 } else {
89- if (EXPECTED (len - i >= 2 )) {
90- parser -> length = (uint16_t )data [i + 1 ];
91- i += 2 ;
92- } else {
93- parser -> require = 2 ;
94- }
84+ parser -> require = 2 ;
9585 }
86+ SET_STATE (s_length );
87+ } else if (EXPECTED (parser -> flags & WS_HAS_MASK )) {
88+ SET_STATE (s_mask );
89+ parser -> require = 4 ;
90+ } else if (EXPECTED (parser -> length )) {
91+ SET_STATE (s_body );
92+ parser -> require = parser -> length ;
93+ NOTIFY_CB (frame_header );
9694 } else {
95+ SET_STATE (s_start );
96+ NOTIFY_CB (frame_header );
97+ NOTIFY_CB (frame_end );
9798 }
98- if (EXPECTED (parser -> require )) {
99- parser -> state = s_length ;
100- } else {
101- if (EXPECTED (parser -> flags & WS_HAS_MASK )) {
102- parser -> state = s_mask ;
99+
100+ header_size ++ ;
101+ break ;
102+ case s_length :
103+ while (HAS_DATA () && parser -> require ) {
104+ parser -> length <<= 8 ;
105+ parser -> length |= (unsigned char )CC ;
106+ parser -> require -- ;
107+ header_size ++ ;
108+ p ++ ;
109+ }
110+ p -- ;
111+ if (UNEXPECTED (!parser -> require )) {
112+ if (EXPECTED (parser -> flags & WS_HAS_MASK )) {
113+ SET_STATE (s_mask );
103114 parser -> require = 4 ;
104- } else if (EXPECTED (parser -> length )) {
115+ } else if (EXPECTED (parser -> length )) {
116+ SET_STATE (s_body );
105117 parser -> require = parser -> length ;
106118 NOTIFY_CB (frame_header );
107- parser -> state = s_body ;
108119 } else {
120+ SET_STATE (s_start );
109121 NOTIFY_CB (frame_header );
110122 NOTIFY_CB (frame_end );
111- parser -> state = s_start ;
112123 }
113124 }
114125 break ;
115- case s_length :
116- while (i < len && parser -> require ) {
117- parser -> length <<= 8 ;
118- parser -> length |= (unsigned char )data [i ++ ];
119- parser -> require -- ;
120- }
121- i -- ;
122- if (!UNEXPECTED (parser -> require )) {
123- parser -> require = parser -> length ;
124- NOTIFY_CB (frame_header );
125- parser -> state = s_body ;
126- }
127- break ;
128126 case s_mask :
129- while (i < len && parser -> require ) {
130- parser -> mask [4 - parser -> require -- ] = data [i ++ ];
127+ while (HAS_DATA () && parser -> require ) {
128+ parser -> mask [4 - parser -> require -- ] = CC ;
129+ header_size ++ ;
130+ p ++ ;
131131 }
132- i -- ;
133- if (! UNEXPECTED (parser -> require )) {
132+ p -- ;
133+ if (UNEXPECTED (! parser -> require )) {
134134 if (parser -> length ) {
135+ SET_STATE (s_body );
135136 parser -> require = parser -> length ;
136137 NOTIFY_CB (frame_header );
137- parser -> state = s_body ;
138138 } else {
139+ SET_STATE (s_start );
139140 NOTIFY_CB (frame_header );
140141 NOTIFY_CB (frame_end );
141- parser -> state = s_start ;
142142 }
143143 }
144144 break ;
145145 case s_body :
146146 if (EXPECTED (parser -> require )) {
147- r = parser -> require ;
148- parser -> require -= len - i ;
149- EMIT_DATA_CB (frame_body , & data [i ], len - i );
150- parser -> offset = len - parser -> require ;
151- i += r ;
147+ if (p + parser -> require <= end ) {
148+ EMIT_DATA_CB (frame_body , p , parser -> require );
149+ p += parser -> require ;
150+ parser -> require = 0 ;
151+ } else {
152+ EMIT_DATA_CB (frame_body , p , end - p );
153+ parser -> require -= end - p ;
154+ p = end ;
155+ parser -> offset += p - data - header_size ;
156+ }
157+
158+ p -- ;
152159 }
153- if (! UNEXPECTED (parser -> require )) {
160+ if (UNEXPECTED (! parser -> require )) {
154161 NOTIFY_CB (frame_end );
155- parser -> state = s_start ;
162+ SET_STATE ( s_start ) ;
156163 }
157164 break ;
158165 default :
159- parser -> error = ERR_UNKNOWN_STATE ;
160- return i ;
166+ assert (0 && "Unreachable case" );
161167 }
162- i ++ ;
163168 }
164169
165- return i ;
170+ return GET_PARSED () ;
166171}
167172
168173void websocket_parser_decode (char * dst , const char * src , size_t len , websocket_parser * parser ) {
@@ -171,7 +176,7 @@ void websocket_parser_decode(char * dst, const char * src, size_t len, websocket
171176 dst [i ] = src [i ] ^ parser -> mask [(i + parser -> mask_offset ) % 4 ];
172177 }
173178
174- parser -> mask_offset = (uint8_t ) ((i + parser -> mask_offset + 1 ) % 4 );
179+ parser -> mask_offset = (uint8_t ) ((i + parser -> mask_offset ) % 4 );
175180}
176181
177182uint8_t websocket_decode (char * dst , const char * src , size_t len , char mask [4 ], uint8_t mask_offset ) {
0 commit comments