-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhttp_header_decode.c
137 lines (127 loc) · 3.41 KB
/
http_header_decode.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "httpkit/http_retcode.h"
#include "kvpair.h"
#include "http_header_decode.h"
int http_header_decode(const char* data, unsigned long len, const char* base,
struct cvector* kvpair_list, unsigned long* offset) {
int rc;
const char* cursor = data;
const char* end = data + len;
unsigned long key_off, key_len, value_off, value_len;
HEADER_ITEM_BEGIN:
key_off = key_len = value_off = value_len = 0;
while (1) {
if (cursor == end) {
return HRC_MORE_DATA;
}
if (*cursor != ' ' && *cursor != '\t') {
break;
}
++cursor;
}
if (*cursor == ':' /* empty key */ || *cursor == '\n') {
return HRC_HEADER;
}
if (*cursor == '\r') {
goto HEADER_ITEM_EMPTY_r; /* empty header */
}
key_off = cursor - base;
/* HEADER_ITEM_KEY */
while (1) {
++cursor;
if (cursor == end) {
return HRC_MORE_DATA;
}
if (*cursor == '\r' || *cursor == '\n') {
return HRC_HEADER;
}
if (*cursor == ' ' || *cursor == '\t') {
key_len = cursor - base - key_off;
/* space(s) between key and colon */
do {
++cursor;
if (cursor == end) {
return HRC_MORE_DATA;
}
} while (*cursor == ' ' || *cursor == '\t');
if (*cursor == ':') {
break;
}
return HRC_HEADER;
}
if (*cursor == ':') {
key_len = cursor - base - key_off;
break;
}
}
/* HEADER_ITEM_COLON */
++cursor;
if (cursor == end) {
return HRC_MORE_DATA;
}
if (*cursor == '\r' || *cursor == '\n') {
return HRC_HEADER;
}
if (*cursor != ' ' && *cursor != '\t') {
value_off = cursor - base;
goto HEADER_ITEM_VALUE;
}
/* space(s) between colon and value */
do {
++cursor;
if (cursor == end) {
return HRC_MORE_DATA;
}
if (*cursor == '\r' || *cursor == '\n') {
return HRC_HEADER;
}
} while (*cursor == ' ' || *cursor == '\t');
value_off = cursor - base;
HEADER_ITEM_VALUE:
{
const char* last_non_space = cursor;
while (1) {
++cursor;
if (cursor == end) {
return HRC_MORE_DATA;
}
if (*cursor == '\n') {
return HRC_HEADER;
}
if (*cursor == '\r') {
value_len = last_non_space + 1 - base - value_off;
break;
}
if (*cursor != ' ' && *cursor != '\t') {
last_non_space = cursor;
}
}
}
/* HEADER_ITEM_r */
++cursor;
if (cursor == end) {
return HRC_MORE_DATA;
}
if (*cursor != '\n') {
return HRC_HEADER;
}
/* HEADER_ITEM_END */
rc = kvpair_vector_update(kvpair_list, (void*)base, key_off, key_len,
value_off, value_len);
if (rc != HRC_OK) {
return rc;
}
++cursor; /* skips '\n' */
(*offset) += (cursor - data);
data = cursor;
goto HEADER_ITEM_BEGIN;
HEADER_ITEM_EMPTY_r:
++cursor;
if (cursor == end) {
return HRC_MORE_DATA;
}
if (*cursor == '\n') {
(*offset) += (cursor - data) + 1;
return HRC_OK;
}
return HRC_HEADER;
}