llhttp_support.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include <stdio.h>
  2. #ifndef LLHTTP__TEST
  3. # include "llhttp.h"
  4. #else
  5. # define llhttp_t llparse_t
  6. #endif /* */
  7. int llhttp_message_needs_eof(const llhttp_t* parser);
  8. int llhttp_should_keep_alive(const llhttp_t* parser);
  9. int llhttp__before_headers_complete(llhttp_t* parser, const char* p,
  10. const char* endp) {
  11. /* Set this here so that on_headers_complete() callbacks can see it */
  12. if ((parser->flags & F_UPGRADE) &&
  13. (parser->flags & F_CONNECTION_UPGRADE)) {
  14. /* For responses, "Upgrade: foo" and "Connection: upgrade" are
  15. * mandatory only when it is a 101 Switching Protocols response,
  16. * otherwise it is purely informational, to announce support.
  17. */
  18. parser->upgrade =
  19. (parser->type == HTTP_REQUEST || parser->status_code == 101);
  20. } else {
  21. parser->upgrade = (parser->method == HTTP_CONNECT);
  22. }
  23. return 0;
  24. }
  25. /* Return values:
  26. * 0 - No body, `restart`, message_complete
  27. * 1 - CONNECT request, `restart`, message_complete, and pause
  28. * 2 - chunk_size_start
  29. * 3 - body_identity
  30. * 4 - body_identity_eof
  31. * 5 - invalid transfer-encoding for request
  32. */
  33. int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
  34. const char* endp) {
  35. int hasBody;
  36. hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
  37. if (
  38. (parser->upgrade && (parser->method == HTTP_CONNECT ||
  39. (parser->flags & F_SKIPBODY) || !hasBody)) ||
  40. /* See RFC 2616 section 4.4 - 1xx e.g. Continue */
  41. (parser->type == HTTP_RESPONSE && parser->status_code == 101)
  42. ) {
  43. /* Exit, the rest of the message is in a different protocol. */
  44. return 1;
  45. }
  46. if (parser->type == HTTP_RESPONSE && parser->status_code == 100) {
  47. /* No body, restart as the message is complete */
  48. return 0;
  49. }
  50. /* See RFC 2616 section 4.4 */
  51. if (
  52. parser->flags & F_SKIPBODY || /* response to a HEAD request */
  53. (
  54. parser->type == HTTP_RESPONSE && (
  55. parser->status_code == 102 || /* Processing */
  56. parser->status_code == 103 || /* Early Hints */
  57. parser->status_code == 204 || /* No Content */
  58. parser->status_code == 304 /* Not Modified */
  59. )
  60. )
  61. ) {
  62. return 0;
  63. } else if (parser->flags & F_CHUNKED) {
  64. /* chunked encoding - ignore Content-Length header, prepare for a chunk */
  65. return 2;
  66. } else if (parser->flags & F_TRANSFER_ENCODING) {
  67. if (parser->type == HTTP_REQUEST &&
  68. (parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0 &&
  69. (parser->lenient_flags & LENIENT_TRANSFER_ENCODING) == 0) {
  70. /* RFC 7230 3.3.3 */
  71. /* If a Transfer-Encoding header field
  72. * is present in a request and the chunked transfer coding is not
  73. * the final encoding, the message body length cannot be determined
  74. * reliably; the server MUST respond with the 400 (Bad Request)
  75. * status code and then close the connection.
  76. */
  77. return 5;
  78. } else {
  79. /* RFC 7230 3.3.3 */
  80. /* If a Transfer-Encoding header field is present in a response and
  81. * the chunked transfer coding is not the final encoding, the
  82. * message body length is determined by reading the connection until
  83. * it is closed by the server.
  84. */
  85. return 4;
  86. }
  87. } else {
  88. if (!(parser->flags & F_CONTENT_LENGTH)) {
  89. if (!llhttp_message_needs_eof(parser)) {
  90. /* Assume content-length 0 - read the next */
  91. return 0;
  92. } else {
  93. /* Read body until EOF */
  94. return 4;
  95. }
  96. } else if (parser->content_length == 0) {
  97. /* Content-Length header given but zero: Content-Length: 0\r\n */
  98. return 0;
  99. } else {
  100. /* Content-Length header given and non-zero */
  101. return 3;
  102. }
  103. }
  104. }
  105. int llhttp__after_message_complete(llhttp_t* parser, const char* p,
  106. const char* endp) {
  107. int should_keep_alive;
  108. should_keep_alive = llhttp_should_keep_alive(parser);
  109. parser->finish = HTTP_FINISH_SAFE;
  110. parser->flags = 0;
  111. /* NOTE: this is ignored in loose parsing mode */
  112. return should_keep_alive;
  113. }
  114. int llhttp_message_needs_eof(const llhttp_t* parser) {
  115. if (parser->type == HTTP_REQUEST) {
  116. return 0;
  117. }
  118. /* See RFC 2616 section 4.4 */
  119. if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
  120. parser->status_code == 204 || /* No Content */
  121. parser->status_code == 304 || /* Not Modified */
  122. (parser->flags & F_SKIPBODY)) { /* response to a HEAD request */
  123. return 0;
  124. }
  125. /* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
  126. if ((parser->flags & F_TRANSFER_ENCODING) &&
  127. (parser->flags & F_CHUNKED) == 0) {
  128. return 1;
  129. }
  130. if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
  131. return 0;
  132. }
  133. return 1;
  134. }
  135. int llhttp_should_keep_alive(const llhttp_t* parser) {
  136. if (parser->http_major > 0 && parser->http_minor > 0) {
  137. /* HTTP/1.1 */
  138. if (parser->flags & F_CONNECTION_CLOSE) {
  139. return 0;
  140. }
  141. } else {
  142. /* HTTP/1.0 or earlier */
  143. if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
  144. return 0;
  145. }
  146. }
  147. return !llhttp_message_needs_eof(parser);
  148. }