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