Skip to content

Commit a3934e2

Browse files
committed
optimization
1 parent 9e9dd46 commit a3934e2

File tree

2 files changed

+58
-55
lines changed

2 files changed

+58
-55
lines changed

websocket_parser.c

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,22 @@
22
#include <assert.h>
33
#include <string.h>
44

5-
6-
#ifdef __GNUC__
7-
# define EXPECTED(X) __builtin_expect(!!(X), 1)
8-
# define UNEXPECTED(X) __builtin_expect(!!(X), 0)
5+
#ifdef assert
6+
# define assertFalse(msg) assert(0 && msg)
97
#else
10-
# define EXPECTED(X) (X)
11-
# define UNEXPECTED(X) (X)
8+
# define assertFalse(msg)
129
#endif
1310

1411
#define SET_STATE(V) parser->state = V
1512
#define HAS_DATA() (p < end )
1613
#define CC (*p)
17-
#define GET_PARSED() ( (p == end) ? len : (p - data) )
14+
#define GET_NPARSED() ( (p == end) ? len : (p - data) )
1815

1916
#define NOTIFY_CB(FOR) \
2017
do { \
2118
if (settings->on_##FOR) { \
2219
if (settings->on_##FOR(parser) != 0) { \
23-
return GET_PARSED(); \
20+
return GET_NPARSED(); \
2421
} \
2522
} \
2623
} while (0)
@@ -29,7 +26,7 @@ do { \
2926
do { \
3027
if (settings->on_##FOR) { \
3128
if (settings->on_##FOR(parser, ptr, len) != 0) { \
32-
return GET_PARSED(); \
29+
return GET_NPARSED(); \
3330
} \
3431
} \
3532
} while (0)
@@ -47,7 +44,6 @@ void websocket_parser_init(websocket_parser * parser) {
4744
memset(parser, 0, sizeof(*parser));
4845
parser->data = data;
4946
parser->state = s_start;
50-
parser->error = 0;
5147
}
5248

5349
void websocket_parser_settings_init(websocket_parser_settings *settings) {
@@ -65,8 +61,8 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser
6561
parser->offset = 0;
6662
parser->length = 0;
6763
parser->mask_offset = 0;
68-
parser->flags = (uint32_t) (CC & WS_OP_MASK);
69-
if(EXPECTED(CC & (1<<7))) {
64+
parser->flags = (websocket_flags) (CC & WS_OP_MASK);
65+
if(CC & (1<<7)) {
7066
parser->flags |= WS_FIN;
7167
}
7268
SET_STATE(s_head);
@@ -78,18 +74,18 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser
7874
if(CC & 0x80) {
7975
parser->flags |= WS_HAS_MASK;
8076
}
81-
if(EXPECTED(parser->length >= 126)) {
82-
if(EXPECTED(parser->length == 127)) {
77+
if(parser->length >= 126) {
78+
if(parser->length == 127) {
8379
parser->require = 8;
8480
} else {
8581
parser->require = 2;
8682
}
8783
parser->length = 0;
8884
SET_STATE(s_length);
89-
} else if (EXPECTED(parser->flags & WS_HAS_MASK)) {
85+
} else if (parser->flags & WS_HAS_MASK) {
9086
SET_STATE(s_mask);
9187
parser->require = 4;
92-
} else if (EXPECTED(parser->length)) {
88+
} else if (parser->length) {
9389
SET_STATE(s_body);
9490
parser->require = parser->length;
9591
NOTIFY_CB(frame_header);
@@ -110,11 +106,11 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser
110106
p++;
111107
}
112108
p--;
113-
if(UNEXPECTED(!parser->require)) {
114-
if (EXPECTED(parser->flags & WS_HAS_MASK)) {
109+
if(!parser->require) {
110+
if (parser->flags & WS_HAS_MASK) {
115111
SET_STATE(s_mask);
116112
parser->require = 4;
117-
} else if (EXPECTED(parser->length)) {
113+
} else if (parser->length) {
118114
SET_STATE(s_body);
119115
parser->require = parser->length;
120116
NOTIFY_CB(frame_header);
@@ -132,7 +128,7 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser
132128
p++;
133129
}
134130
p--;
135-
if(UNEXPECTED(!parser->require)) {
131+
if(!parser->require) {
136132
if(parser->length) {
137133
SET_STATE(s_body);
138134
parser->require = parser->length;
@@ -145,7 +141,7 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser
145141
}
146142
break;
147143
case s_body:
148-
if(EXPECTED(parser->require)) {
144+
if(parser->require) {
149145
if(p + parser->require <= end) {
150146
EMIT_DATA_CB(frame_body, p, parser->require);
151147
p += parser->require;
@@ -161,17 +157,17 @@ size_t websocket_parser_execute(websocket_parser *parser, const websocket_parser
161157

162158
p--;
163159
}
164-
if(UNEXPECTED(!parser->require)) {
160+
if(!parser->require) {
165161
NOTIFY_CB(frame_end);
166162
SET_STATE(s_start);
167163
}
168164
break;
169165
default:
170-
assert(0 && "Unreachable case");
166+
assertFalse("Unreachable case");
171167
}
172168
}
173169

174-
return GET_PARSED();
170+
return GET_NPARSED();
175171
}
176172

177173
void websocket_parser_decode(char * dst, const char * src, size_t len, websocket_parser * parser) {
@@ -192,23 +188,23 @@ uint8_t websocket_decode(char * dst, const char * src, size_t len, const char ma
192188
return (uint8_t) ((i + mask_offset) % 4);
193189
}
194190

195-
size_t websocket_calc_frame_size(uint32_t flags, size_t data_len) {
191+
size_t websocket_calc_frame_size(websocket_flags flags, size_t data_len) {
196192
size_t size = data_len + 2; // body + 2 bytes of head
197-
if(EXPECTED(data_len >= 126)) {
198-
if(EXPECTED(data_len > 0xFFFF)) {
193+
if(data_len >= 126) {
194+
if(data_len > 0xFFFF) {
199195
size += 8;
200196
} else {
201197
size += 2;
202198
}
203199
}
204-
if(EXPECTED(flags & WS_HAS_MASK)) {
200+
if(flags & WS_HAS_MASK) {
205201
size += 4;
206202
}
207203

208204
return size;
209205
}
210206

211-
size_t websocket_build_frame(char * frame, uint32_t flags, const char mask[4], const char * data, size_t data_len) {
207+
size_t websocket_build_frame(char * frame, websocket_flags flags, const char mask[4], const char * data, size_t data_len) {
212208
size_t body_offset = 0;
213209
frame[0] = 0;
214210
frame[1] = 0;

websocket_parser.h

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,41 +28,36 @@ typedef unsigned __int64 uint64_t;
2828
typedef struct websocket_parser websocket_parser;
2929
typedef struct websocket_parser_settings websocket_parser_settings;
3030

31-
enum websocket_ops {
31+
typedef enum websocket_flags {
32+
// opcodes
3233
WS_OP_CONTINUE = 0x0,
3334
WS_OP_TEXT = 0x1,
3435
WS_OP_BINARY = 0x2,
3536
WS_OP_CLOSE = 0x8,
3637
WS_OP_PING = 0x9,
3738
WS_OP_PONG = 0xA,
38-
};
39-
40-
#define WS_OP_MASK 0xF
4139

42-
enum websocket_errors {
43-
ERR_OK,
44-
ERR_UNKNOWN_STATE,
45-
};
40+
// marks
41+
WS_FINAL_FRAME = 0x10,
42+
WS_HAS_MASK = 0x20,
43+
} websocket_flags;
4644

47-
enum websocket_flags {
48-
WS_FIN = 0x10,
49-
WS_HAS_MASK = 0x20,
50-
};
45+
#define WS_OP_MASK 0xF
46+
#define WS_FIN WS_FINAL_FRAME
5147

52-
typedef int (*websocket_data_cb) (websocket_parser*, const char *at, size_t length);
48+
typedef int (*websocket_data_cb) (websocket_parser*, const char * at, size_t length);
5349
typedef int (*websocket_cb) (websocket_parser*);
5450

5551
struct websocket_parser {
56-
uint32_t state;
57-
uint32_t flags;
58-
uint32_t error;
59-
char mask[4];
60-
uint8_t mask_offset;
52+
uint32_t state;
53+
websocket_flags flags;
6154

62-
uint32_t nread;
63-
size_t length;
64-
size_t require;
65-
size_t offset;
55+
char mask[4];
56+
uint8_t mask_offset;
57+
58+
size_t length;
59+
size_t require;
60+
size_t offset;
6661

6762
void * data;
6863
};
@@ -76,16 +71,28 @@ struct websocket_parser_settings {
7671
void websocket_parser_init(websocket_parser *parser);
7772
void websocket_parser_settings_init(websocket_parser_settings *settings);
7873
size_t websocket_parser_execute(
79-
websocket_parser *parser,
74+
websocket_parser * parser,
8075
const websocket_parser_settings *settings,
81-
const char *data,
76+
const char * data,
8277
size_t len
8378
);
79+
80+
// Apply XOR mask (see https://tools.ietf.org/html/rfc6455#section-5.3) and store mask's offset
8481
void websocket_parser_decode(char * dst, const char * src, size_t len, websocket_parser * parser);
82+
83+
// Apply XOR mask (see https://tools.ietf.org/html/rfc6455#section-5.3) and return mask's offset
8584
uint8_t websocket_decode(char * dst, const char * src, size_t len, const char mask[4], uint8_t mask_offset);
8685
#define websocket_encode(dst, src, len, mask, mask_offset) websocket_decode(dst, src, len, mask, mask_offset)
87-
size_t websocket_calc_frame_size(uint32_t flags, size_t data_len);
88-
size_t websocket_build_frame(char * frame, uint32_t flags, const char mask[4], const char * data, size_t data_len);
86+
87+
// Calculate frame size using flags and data length
88+
size_t websocket_calc_frame_size(websocket_flags flags, size_t data_len);
89+
90+
// Create string representation of frame
91+
size_t websocket_build_frame(char * frame, websocket_flags flags, const char mask[4], const char * data, size_t data_len);
92+
93+
#define websocket_parser_get_opcode(p) (p->flags & WS_OP_MASK)
94+
#define websocket_parser_has_mask(p) (p->flags & WS_HAS_MASK)
95+
#define websocket_parser_has_final(p) (p->flags & WS_FIN)
8996

9097
#ifdef __cplusplus
9198
}

0 commit comments

Comments
 (0)