| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- #include <stdio.h>
- #ifndef LLHTTP__TEST
- # include "llhttp.h"
- #else
- # define llhttp_t llparse_t
- #endif /* */
- int llhttp_message_needs_eof(const llhttp_t* parser);
- int llhttp_should_keep_alive(const llhttp_t* parser);
- int llhttp__before_headers_complete(llhttp_t* parser, const char* p,
- const char* endp) {
- /* Set this here so that on_headers_complete() callbacks can see it */
- if ((parser->flags & F_UPGRADE) &&
- (parser->flags & F_CONNECTION_UPGRADE)) {
- /* For responses, "Upgrade: foo" and "Connection: upgrade" are
- * mandatory only when it is a 101 Switching Protocols response,
- * otherwise it is purely informational, to announce support.
- */
- parser->upgrade =
- (parser->type == HTTP_REQUEST || parser->status_code == 101);
- } else {
- parser->upgrade = (parser->method == HTTP_CONNECT);
- }
- return 0;
- }
- /* Return values:
- * 0 - No body, `restart`, message_complete
- * 1 - CONNECT request, `restart`, message_complete, and pause
- * 2 - chunk_size_start
- * 3 - body_identity
- * 4 - body_identity_eof
- * 5 - invalid transfer-encoding for request
- */
- int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
- const char* endp) {
- int hasBody;
- hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
- if (
- (parser->upgrade && (parser->method == HTTP_CONNECT ||
- (parser->flags & F_SKIPBODY) || !hasBody)) ||
- /* See RFC 2616 section 4.4 - 1xx e.g. Continue */
- (parser->type == HTTP_RESPONSE && parser->status_code == 101)
- ) {
- /* Exit, the rest of the message is in a different protocol. */
- return 1;
- }
- if (parser->type == HTTP_RESPONSE && parser->status_code == 100) {
- /* No body, restart as the message is complete */
- return 0;
- }
- /* See RFC 2616 section 4.4 */
- if (
- parser->flags & F_SKIPBODY || /* response to a HEAD request */
- (
- parser->type == HTTP_RESPONSE && (
- parser->status_code == 102 || /* Processing */
- parser->status_code == 103 || /* Early Hints */
- parser->status_code == 204 || /* No Content */
- parser->status_code == 304 /* Not Modified */
- )
- )
- ) {
- return 0;
- } else if (parser->flags & F_CHUNKED) {
- /* chunked encoding - ignore Content-Length header, prepare for a chunk */
- return 2;
- } else if (parser->flags & F_TRANSFER_ENCODING) {
- if (parser->type == HTTP_REQUEST &&
- (parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 &&
- (parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) {
- /* RFC 7230 3.3.3 */
- /* If a Transfer-Encoding header field
- * is present in a request and the chunked transfer coding is not
- * the final encoding, the message body length cannot be determined
- * reliably; the server MUST respond with the 400 (Bad Request)
- * status code and then close the connection.
- */
- return 5;
- } else {
- /* RFC 7230 3.3.3 */
- /* If a Transfer-Encoding header field is present in a response and
- * the chunked transfer coding is not the final encoding, the
- * message body length is determined by reading the connection until
- * it is closed by the server.
- */
- return 4;
- }
- } else {
- if (!(parser->flags & F_CONTENT_LENGTH)) {
- if (!llhttp_message_needs_eof(parser)) {
- /* Assume content-length 0 - read the next */
- return 0;
- } else {
- /* Read body until EOF */
- return 4;
- }
- } else if (parser->content_length == 0) {
- /* Content-Length header given but zero: Content-Length: 0\r\n */
- return 0;
- } else {
- /* Content-Length header given and non-zero */
- return 3;
- }
- }
- }
- int llhttp__after_message_complete(llhttp_t* parser, const char* p,
- const char* endp) {
- int should_keep_alive;
- should_keep_alive = llhttp_should_keep_alive(parser);
- parser->finish = HTTP_FINISH_SAFE;
- parser->flags = 0;
- /* NOTE: this is ignored in loose parsing mode */
- return should_keep_alive;
- }
- int llhttp_message_needs_eof(const llhttp_t* parser) {
- if (parser->type == HTTP_REQUEST) {
- return 0;
- }
- /* See RFC 2616 section 4.4 */
- if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
- parser->status_code == 204 || /* No Content */
- parser->status_code == 304 || /* Not Modified */
- (parser->flags & F_SKIPBODY)) { /* response to a HEAD request */
- return 0;
- }
- /* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
- if ((parser->flags & F_TRANSFER_ENCODING) &&
- (parser->flags & F_CHUNKED) == 0) {
- return 1;
- }
- if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
- return 0;
- }
- return 1;
- }
- int llhttp_should_keep_alive(const llhttp_t* parser) {
- if (parser->http_major > 0 && parser->http_minor > 0) {
- /* HTTP/1.1 */
- if (parser->flags & F_CONNECTION_CLOSE) {
- return 0;
- }
- } else {
- /* HTTP/1.0 or earlier */
- if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
- return 0;
- }
- }
- return !llhttp_message_needs_eof(parser);
- }
|