11cb0ef41Sopenharmony_ci#include <stdio.h> 21cb0ef41Sopenharmony_ci#ifndef LLHTTP__TEST 31cb0ef41Sopenharmony_ci# include "llhttp.h" 41cb0ef41Sopenharmony_ci#else 51cb0ef41Sopenharmony_ci# define llhttp_t llparse_t 61cb0ef41Sopenharmony_ci#endif /* */ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ciint llhttp_message_needs_eof(const llhttp_t* parser); 91cb0ef41Sopenharmony_ciint llhttp_should_keep_alive(const llhttp_t* parser); 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ciint llhttp__before_headers_complete(llhttp_t* parser, const char* p, 121cb0ef41Sopenharmony_ci const char* endp) { 131cb0ef41Sopenharmony_ci /* Set this here so that on_headers_complete() callbacks can see it */ 141cb0ef41Sopenharmony_ci if ((parser->flags & F_UPGRADE) && 151cb0ef41Sopenharmony_ci (parser->flags & F_CONNECTION_UPGRADE)) { 161cb0ef41Sopenharmony_ci /* For responses, "Upgrade: foo" and "Connection: upgrade" are 171cb0ef41Sopenharmony_ci * mandatory only when it is a 101 Switching Protocols response, 181cb0ef41Sopenharmony_ci * otherwise it is purely informational, to announce support. 191cb0ef41Sopenharmony_ci */ 201cb0ef41Sopenharmony_ci parser->upgrade = 211cb0ef41Sopenharmony_ci (parser->type == HTTP_REQUEST || parser->status_code == 101); 221cb0ef41Sopenharmony_ci } else { 231cb0ef41Sopenharmony_ci parser->upgrade = (parser->method == HTTP_CONNECT); 241cb0ef41Sopenharmony_ci } 251cb0ef41Sopenharmony_ci return 0; 261cb0ef41Sopenharmony_ci} 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci/* Return values: 301cb0ef41Sopenharmony_ci * 0 - No body, `restart`, message_complete 311cb0ef41Sopenharmony_ci * 1 - CONNECT request, `restart`, message_complete, and pause 321cb0ef41Sopenharmony_ci * 2 - chunk_size_start 331cb0ef41Sopenharmony_ci * 3 - body_identity 341cb0ef41Sopenharmony_ci * 4 - body_identity_eof 351cb0ef41Sopenharmony_ci * 5 - invalid transfer-encoding for request 361cb0ef41Sopenharmony_ci */ 371cb0ef41Sopenharmony_ciint llhttp__after_headers_complete(llhttp_t* parser, const char* p, 381cb0ef41Sopenharmony_ci const char* endp) { 391cb0ef41Sopenharmony_ci int hasBody; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci hasBody = parser->flags & F_CHUNKED || parser->content_length > 0; 421cb0ef41Sopenharmony_ci if (parser->upgrade && (parser->method == HTTP_CONNECT || 431cb0ef41Sopenharmony_ci (parser->flags & F_SKIPBODY) || !hasBody)) { 441cb0ef41Sopenharmony_ci /* Exit, the rest of the message is in a different protocol. */ 451cb0ef41Sopenharmony_ci return 1; 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci if (parser->flags & F_SKIPBODY) { 491cb0ef41Sopenharmony_ci return 0; 501cb0ef41Sopenharmony_ci } else if (parser->flags & F_CHUNKED) { 511cb0ef41Sopenharmony_ci /* chunked encoding - ignore Content-Length header, prepare for a chunk */ 521cb0ef41Sopenharmony_ci return 2; 531cb0ef41Sopenharmony_ci } else if (parser->flags & F_TRANSFER_ENCODING) { 541cb0ef41Sopenharmony_ci if (parser->type == HTTP_REQUEST && 551cb0ef41Sopenharmony_ci (parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 && 561cb0ef41Sopenharmony_ci (parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) { 571cb0ef41Sopenharmony_ci /* RFC 7230 3.3.3 */ 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci /* If a Transfer-Encoding header field 601cb0ef41Sopenharmony_ci * is present in a request and the chunked transfer coding is not 611cb0ef41Sopenharmony_ci * the final encoding, the message body length cannot be determined 621cb0ef41Sopenharmony_ci * reliably; the server MUST respond with the 400 (Bad Request) 631cb0ef41Sopenharmony_ci * status code and then close the connection. 641cb0ef41Sopenharmony_ci */ 651cb0ef41Sopenharmony_ci return 5; 661cb0ef41Sopenharmony_ci } else { 671cb0ef41Sopenharmony_ci /* RFC 7230 3.3.3 */ 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci /* If a Transfer-Encoding header field is present in a response and 701cb0ef41Sopenharmony_ci * the chunked transfer coding is not the final encoding, the 711cb0ef41Sopenharmony_ci * message body length is determined by reading the connection until 721cb0ef41Sopenharmony_ci * it is closed by the server. 731cb0ef41Sopenharmony_ci */ 741cb0ef41Sopenharmony_ci return 4; 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci } else { 771cb0ef41Sopenharmony_ci if (!(parser->flags & F_CONTENT_LENGTH)) { 781cb0ef41Sopenharmony_ci if (!llhttp_message_needs_eof(parser)) { 791cb0ef41Sopenharmony_ci /* Assume content-length 0 - read the next */ 801cb0ef41Sopenharmony_ci return 0; 811cb0ef41Sopenharmony_ci } else { 821cb0ef41Sopenharmony_ci /* Read body until EOF */ 831cb0ef41Sopenharmony_ci return 4; 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci } else if (parser->content_length == 0) { 861cb0ef41Sopenharmony_ci /* Content-Length header given but zero: Content-Length: 0\r\n */ 871cb0ef41Sopenharmony_ci return 0; 881cb0ef41Sopenharmony_ci } else { 891cb0ef41Sopenharmony_ci /* Content-Length header given and non-zero */ 901cb0ef41Sopenharmony_ci return 3; 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ciint llhttp__after_message_complete(llhttp_t* parser, const char* p, 971cb0ef41Sopenharmony_ci const char* endp) { 981cb0ef41Sopenharmony_ci int should_keep_alive; 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci should_keep_alive = llhttp_should_keep_alive(parser); 1011cb0ef41Sopenharmony_ci parser->finish = HTTP_FINISH_SAFE; 1021cb0ef41Sopenharmony_ci parser->flags = 0; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci /* NOTE: this is ignored in loose parsing mode */ 1051cb0ef41Sopenharmony_ci return should_keep_alive; 1061cb0ef41Sopenharmony_ci} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ciint llhttp_message_needs_eof(const llhttp_t* parser) { 1101cb0ef41Sopenharmony_ci if (parser->type == HTTP_REQUEST) { 1111cb0ef41Sopenharmony_ci return 0; 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci /* See RFC 2616 section 4.4 */ 1151cb0ef41Sopenharmony_ci if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ 1161cb0ef41Sopenharmony_ci parser->status_code == 204 || /* No Content */ 1171cb0ef41Sopenharmony_ci parser->status_code == 304 || /* Not Modified */ 1181cb0ef41Sopenharmony_ci (parser->flags & F_SKIPBODY)) { /* response to a HEAD request */ 1191cb0ef41Sopenharmony_ci return 0; 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci /* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */ 1231cb0ef41Sopenharmony_ci if ((parser->flags & F_TRANSFER_ENCODING) && 1241cb0ef41Sopenharmony_ci (parser->flags & F_CHUNKED) == 0) { 1251cb0ef41Sopenharmony_ci return 1; 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) { 1291cb0ef41Sopenharmony_ci return 0; 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci return 1; 1331cb0ef41Sopenharmony_ci} 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ciint llhttp_should_keep_alive(const llhttp_t* parser) { 1371cb0ef41Sopenharmony_ci if (parser->http_major > 0 && parser->http_minor > 0) { 1381cb0ef41Sopenharmony_ci /* HTTP/1.1 */ 1391cb0ef41Sopenharmony_ci if (parser->flags & F_CONNECTION_CLOSE) { 1401cb0ef41Sopenharmony_ci return 0; 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci } else { 1431cb0ef41Sopenharmony_ci /* HTTP/1.0 or earlier */ 1441cb0ef41Sopenharmony_ci if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { 1451cb0ef41Sopenharmony_ci return 0; 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci } 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci return !llhttp_message_needs_eof(parser); 1501cb0ef41Sopenharmony_ci} 151