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