12c593315Sopenharmony_ci#include <stdio.h> 22c593315Sopenharmony_ci#ifndef LLHTTP__TEST 32c593315Sopenharmony_ci# include "llhttp.h" 42c593315Sopenharmony_ci#else 52c593315Sopenharmony_ci# define llhttp_t llparse_t 62c593315Sopenharmony_ci#endif /* */ 72c593315Sopenharmony_ci 82c593315Sopenharmony_ciint llhttp_message_needs_eof(const llhttp_t* parser); 92c593315Sopenharmony_ciint llhttp_should_keep_alive(const llhttp_t* parser); 102c593315Sopenharmony_ci 112c593315Sopenharmony_ciint llhttp__before_headers_complete(llhttp_t* parser, const char* p, 122c593315Sopenharmony_ci const char* endp) { 132c593315Sopenharmony_ci /* Set this here so that on_headers_complete() callbacks can see it */ 142c593315Sopenharmony_ci if ((parser->flags & F_UPGRADE) && 152c593315Sopenharmony_ci (parser->flags & F_CONNECTION_UPGRADE)) { 162c593315Sopenharmony_ci /* For responses, "Upgrade: foo" and "Connection: upgrade" are 172c593315Sopenharmony_ci * mandatory only when it is a 101 Switching Protocols response, 182c593315Sopenharmony_ci * otherwise it is purely informational, to announce support. 192c593315Sopenharmony_ci */ 202c593315Sopenharmony_ci parser->upgrade = 212c593315Sopenharmony_ci (parser->type == HTTP_REQUEST || parser->status_code == 101); 222c593315Sopenharmony_ci } else { 232c593315Sopenharmony_ci parser->upgrade = (parser->method == HTTP_CONNECT); 242c593315Sopenharmony_ci } 252c593315Sopenharmony_ci return 0; 262c593315Sopenharmony_ci} 272c593315Sopenharmony_ci 282c593315Sopenharmony_ci 292c593315Sopenharmony_ci/* Return values: 302c593315Sopenharmony_ci * 0 - No body, `restart`, message_complete 312c593315Sopenharmony_ci * 1 - CONNECT request, `restart`, message_complete, and pause 322c593315Sopenharmony_ci * 2 - chunk_size_start 332c593315Sopenharmony_ci * 3 - body_identity 342c593315Sopenharmony_ci * 4 - body_identity_eof 352c593315Sopenharmony_ci * 5 - invalid transfer-encoding for request 362c593315Sopenharmony_ci */ 372c593315Sopenharmony_ciint llhttp__after_headers_complete(llhttp_t* parser, const char* p, 382c593315Sopenharmony_ci const char* endp) { 392c593315Sopenharmony_ci int hasBody; 402c593315Sopenharmony_ci 412c593315Sopenharmony_ci hasBody = parser->flags & F_CHUNKED || parser->content_length > 0; 422c593315Sopenharmony_ci if (parser->upgrade && (parser->method == HTTP_CONNECT || 432c593315Sopenharmony_ci (parser->flags & F_SKIPBODY) || !hasBody)) { 442c593315Sopenharmony_ci /* Exit, the rest of the message is in a different protocol. */ 452c593315Sopenharmony_ci return 1; 462c593315Sopenharmony_ci } 472c593315Sopenharmony_ci 482c593315Sopenharmony_ci if (parser->flags & F_SKIPBODY) { 492c593315Sopenharmony_ci return 0; 502c593315Sopenharmony_ci } else if (parser->flags & F_CHUNKED) { 512c593315Sopenharmony_ci /* chunked encoding - ignore Content-Length header, prepare for a chunk */ 522c593315Sopenharmony_ci return 2; 532c593315Sopenharmony_ci } else if (parser->flags & F_TRANSFER_ENCODING) { 542c593315Sopenharmony_ci if (parser->type == HTTP_REQUEST && 552c593315Sopenharmony_ci (parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 && 562c593315Sopenharmony_ci (parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) { 572c593315Sopenharmony_ci /* RFC 7230 3.3.3 */ 582c593315Sopenharmony_ci 592c593315Sopenharmony_ci /* If a Transfer-Encoding header field 602c593315Sopenharmony_ci * is present in a request and the chunked transfer coding is not 612c593315Sopenharmony_ci * the final encoding, the message body length cannot be determined 622c593315Sopenharmony_ci * reliably; the server MUST respond with the 400 (Bad Request) 632c593315Sopenharmony_ci * status code and then close the connection. 642c593315Sopenharmony_ci */ 652c593315Sopenharmony_ci return 5; 662c593315Sopenharmony_ci } else { 672c593315Sopenharmony_ci /* RFC 7230 3.3.3 */ 682c593315Sopenharmony_ci 692c593315Sopenharmony_ci /* If a Transfer-Encoding header field is present in a response and 702c593315Sopenharmony_ci * the chunked transfer coding is not the final encoding, the 712c593315Sopenharmony_ci * message body length is determined by reading the connection until 722c593315Sopenharmony_ci * it is closed by the server. 732c593315Sopenharmony_ci */ 742c593315Sopenharmony_ci return 4; 752c593315Sopenharmony_ci } 762c593315Sopenharmony_ci } else { 772c593315Sopenharmony_ci if (!(parser->flags & F_CONTENT_LENGTH)) { 782c593315Sopenharmony_ci if (!llhttp_message_needs_eof(parser)) { 792c593315Sopenharmony_ci /* Assume content-length 0 - read the next */ 802c593315Sopenharmony_ci return 0; 812c593315Sopenharmony_ci } else { 822c593315Sopenharmony_ci /* Read body until EOF */ 832c593315Sopenharmony_ci return 4; 842c593315Sopenharmony_ci } 852c593315Sopenharmony_ci } else if (parser->content_length == 0) { 862c593315Sopenharmony_ci /* Content-Length header given but zero: Content-Length: 0\r\n */ 872c593315Sopenharmony_ci return 0; 882c593315Sopenharmony_ci } else { 892c593315Sopenharmony_ci /* Content-Length header given and non-zero */ 902c593315Sopenharmony_ci return 3; 912c593315Sopenharmony_ci } 922c593315Sopenharmony_ci } 932c593315Sopenharmony_ci} 942c593315Sopenharmony_ci 952c593315Sopenharmony_ci 962c593315Sopenharmony_ciint llhttp__after_message_complete(llhttp_t* parser, const char* p, 972c593315Sopenharmony_ci const char* endp) { 982c593315Sopenharmony_ci int should_keep_alive; 992c593315Sopenharmony_ci 1002c593315Sopenharmony_ci should_keep_alive = llhttp_should_keep_alive(parser); 1012c593315Sopenharmony_ci parser->finish = HTTP_FINISH_SAFE; 1022c593315Sopenharmony_ci parser->flags = 0; 1032c593315Sopenharmony_ci 1042c593315Sopenharmony_ci /* NOTE: this is ignored in loose parsing mode */ 1052c593315Sopenharmony_ci return should_keep_alive; 1062c593315Sopenharmony_ci} 1072c593315Sopenharmony_ci 1082c593315Sopenharmony_ci 1092c593315Sopenharmony_ciint llhttp_message_needs_eof(const llhttp_t* parser) { 1102c593315Sopenharmony_ci if (parser->type == HTTP_REQUEST) { 1112c593315Sopenharmony_ci return 0; 1122c593315Sopenharmony_ci } 1132c593315Sopenharmony_ci 1142c593315Sopenharmony_ci /* See RFC 2616 section 4.4 */ 1152c593315Sopenharmony_ci if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ 1162c593315Sopenharmony_ci parser->status_code == 204 || /* No Content */ 1172c593315Sopenharmony_ci parser->status_code == 304 || /* Not Modified */ 1182c593315Sopenharmony_ci (parser->flags & F_SKIPBODY)) { /* response to a HEAD request */ 1192c593315Sopenharmony_ci return 0; 1202c593315Sopenharmony_ci } 1212c593315Sopenharmony_ci 1222c593315Sopenharmony_ci /* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */ 1232c593315Sopenharmony_ci if ((parser->flags & F_TRANSFER_ENCODING) && 1242c593315Sopenharmony_ci (parser->flags & F_CHUNKED) == 0) { 1252c593315Sopenharmony_ci return 1; 1262c593315Sopenharmony_ci } 1272c593315Sopenharmony_ci 1282c593315Sopenharmony_ci if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) { 1292c593315Sopenharmony_ci return 0; 1302c593315Sopenharmony_ci } 1312c593315Sopenharmony_ci 1322c593315Sopenharmony_ci return 1; 1332c593315Sopenharmony_ci} 1342c593315Sopenharmony_ci 1352c593315Sopenharmony_ci 1362c593315Sopenharmony_ciint llhttp_should_keep_alive(const llhttp_t* parser) { 1372c593315Sopenharmony_ci if (parser->http_major > 0 && parser->http_minor > 0) { 1382c593315Sopenharmony_ci /* HTTP/1.1 */ 1392c593315Sopenharmony_ci if (parser->flags & F_CONNECTION_CLOSE) { 1402c593315Sopenharmony_ci return 0; 1412c593315Sopenharmony_ci } 1422c593315Sopenharmony_ci } else { 1432c593315Sopenharmony_ci /* HTTP/1.0 or earlier */ 1442c593315Sopenharmony_ci if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { 1452c593315Sopenharmony_ci return 0; 1462c593315Sopenharmony_ci } 1472c593315Sopenharmony_ci } 1482c593315Sopenharmony_ci 1492c593315Sopenharmony_ci return !llhttp_message_needs_eof(parser); 1502c593315Sopenharmony_ci} 151