• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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