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