1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "llhttp.h"
6
7 #define CALLBACK_MAYBE(PARSER, NAME, ...) \
8 do { \
9 llhttp_settings_t* settings; \
10 settings = (llhttp_settings_t*) (PARSER)->settings; \
11 if (settings == NULL || settings->NAME == NULL) { \
12 err = 0; \
13 break; \
14 } \
15 err = settings->NAME(__VA_ARGS__); \
16 } while (0)
17
llhttp_init(llhttp_t * parser,llhttp_type_t type,const llhttp_settings_t * settings)18 void llhttp_init(llhttp_t* parser, llhttp_type_t type,
19 const llhttp_settings_t* settings) {
20 llhttp__internal_init(parser);
21
22 parser->type = type;
23 parser->settings = (void*) settings;
24 }
25
26
llhttp_execute(llhttp_t * parser,const char * data,size_t len)27 llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) {
28 return llhttp__internal_execute(parser, data, data + len);
29 }
30
31
llhttp_settings_init(llhttp_settings_t * settings)32 void llhttp_settings_init(llhttp_settings_t* settings) {
33 memset(settings, 0, sizeof(*settings));
34 }
35
36
llhttp_finish(llhttp_t * parser)37 llhttp_errno_t llhttp_finish(llhttp_t* parser) {
38 int err;
39
40 /* We're in an error state. Don't bother doing anything. */
41 if (parser->error != 0) {
42 return 0;
43 }
44
45 switch (parser->finish) {
46 case HTTP_FINISH_SAFE_WITH_CB:
47 CALLBACK_MAYBE(parser, on_message_complete, parser);
48 if (err != HPE_OK) return err;
49
50 /* FALLTHROUGH */
51 case HTTP_FINISH_SAFE:
52 return HPE_OK;
53 case HTTP_FINISH_UNSAFE:
54 parser->reason = "Invalid EOF state";
55 return HPE_INVALID_EOF_STATE;
56 default:
57 abort();
58 }
59 }
60
61
llhttp_pause(llhttp_t * parser)62 void llhttp_pause(llhttp_t* parser) {
63 if (parser->error != HPE_OK) {
64 return;
65 }
66
67 parser->error = HPE_PAUSED;
68 parser->reason = "Paused";
69 }
70
71
llhttp_resume(llhttp_t * parser)72 void llhttp_resume(llhttp_t* parser) {
73 if (parser->error != HPE_PAUSED) {
74 return;
75 }
76
77 parser->error = 0;
78 }
79
80
llhttp_resume_after_upgrade(llhttp_t * parser)81 void llhttp_resume_after_upgrade(llhttp_t* parser) {
82 if (parser->error != HPE_PAUSED_UPGRADE) {
83 return;
84 }
85
86 parser->error = 0;
87 }
88
89
llhttp_get_errno(const llhttp_t * parser)90 llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
91 return parser->error;
92 }
93
94
llhttp_get_error_reason(const llhttp_t * parser)95 const char* llhttp_get_error_reason(const llhttp_t* parser) {
96 return parser->reason;
97 }
98
99
llhttp_set_error_reason(llhttp_t * parser,const char * reason)100 void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
101 parser->reason = reason;
102 }
103
104
llhttp_get_error_pos(const llhttp_t * parser)105 const char* llhttp_get_error_pos(const llhttp_t* parser) {
106 return parser->error_pos;
107 }
108
109
llhttp_errno_name(llhttp_errno_t err)110 const char* llhttp_errno_name(llhttp_errno_t err) {
111 #define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME;
112 switch (err) {
113 HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
114 default: abort();
115 }
116 #undef HTTP_ERRNO_GEN
117 }
118
119
llhttp_method_name(llhttp_method_t method)120 const char* llhttp_method_name(llhttp_method_t method) {
121 #define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
122 switch (method) {
123 HTTP_METHOD_MAP(HTTP_METHOD_GEN)
124 default: abort();
125 }
126 #undef HTTP_METHOD_GEN
127 }
128
129
llhttp_set_lenient(llhttp_t * parser,int enabled)130 void llhttp_set_lenient(llhttp_t* parser, int enabled) {
131 if (enabled) {
132 parser->flags |= F_LENIENT;
133 } else {
134 parser->flags &= ~F_LENIENT;
135 }
136 }
137
138
139 /* Callbacks */
140
141
llhttp__on_message_begin(llhttp_t * s,const char * p,const char * endp)142 int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
143 int err;
144 CALLBACK_MAYBE(s, on_message_begin, s);
145 return err;
146 }
147
148
llhttp__on_url(llhttp_t * s,const char * p,const char * endp)149 int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
150 int err;
151 CALLBACK_MAYBE(s, on_url, s, p, endp - p);
152 return err;
153 }
154
155
llhttp__on_status(llhttp_t * s,const char * p,const char * endp)156 int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
157 int err;
158 CALLBACK_MAYBE(s, on_status, s, p, endp - p);
159 return err;
160 }
161
162
llhttp__on_header_field(llhttp_t * s,const char * p,const char * endp)163 int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
164 int err;
165 CALLBACK_MAYBE(s, on_header_field, s, p, endp - p);
166 return err;
167 }
168
169
llhttp__on_header_value(llhttp_t * s,const char * p,const char * endp)170 int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
171 int err;
172 CALLBACK_MAYBE(s, on_header_value, s, p, endp - p);
173 return err;
174 }
175
176
llhttp__on_headers_complete(llhttp_t * s,const char * p,const char * endp)177 int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
178 int err;
179 CALLBACK_MAYBE(s, on_headers_complete, s);
180 return err;
181 }
182
183
llhttp__on_message_complete(llhttp_t * s,const char * p,const char * endp)184 int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
185 int err;
186 CALLBACK_MAYBE(s, on_message_complete, s);
187 return err;
188 }
189
190
llhttp__on_body(llhttp_t * s,const char * p,const char * endp)191 int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
192 int err;
193 CALLBACK_MAYBE(s, on_body, s, p, endp - p);
194 return err;
195 }
196
197
llhttp__on_chunk_header(llhttp_t * s,const char * p,const char * endp)198 int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
199 int err;
200 CALLBACK_MAYBE(s, on_chunk_header, s);
201 return err;
202 }
203
204
llhttp__on_chunk_complete(llhttp_t * s,const char * p,const char * endp)205 int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
206 int err;
207 CALLBACK_MAYBE(s, on_chunk_complete, s);
208 return err;
209 }
210
211
212 /* Private */
213
214
llhttp__debug(llhttp_t * s,const char * p,const char * endp,const char * msg)215 void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
216 const char* msg) {
217 if (p == endp) {
218 fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type,
219 s->flags, msg);
220 } else {
221 fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s,
222 s->type, s->flags, *p, msg);
223 }
224 }
225