Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: monkey: upgrade to v1.8.1 (add support for HTTP/1.1 chunked transfer encoding) #9466

Merged
merged 9 commits into from
Oct 10, 2024
4 changes: 2 additions & 2 deletions lib/monkey/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ endif()

# Monkey Version
set(MK_VERSION_MAJOR 1)
set(MK_VERSION_MINOR 7)
set(MK_VERSION_PATCH 2)
set(MK_VERSION_MINOR 8)
set(MK_VERSION_PATCH 1)
set(MK_VERSION_STR "${MK_VERSION_MAJOR}.${MK_VERSION_MINOR}.${MK_VERSION_PATCH}")

# Output paths
Expand Down
6 changes: 3 additions & 3 deletions lib/monkey/api/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <signal.h>

#define API_ADDR "127.0.0.1"
#define API_PORT "8080"
#define API_PORT "9080"

/* Main context set as global so the signal handler can use it */
mk_ctx_t *ctx;
Expand Down Expand Up @@ -153,9 +153,9 @@ int main()
"Name", "monotop",
NULL);

mk_vhost_handler(ctx, vid, "/api/v1/stream_processor/task/[A-Za-z_][0-9A-Za-z_\\-]*",
mk_vhost_handler(ctx, vid, "/api/v1/stream_processor/task/[A-Za-z_][0-9A-Za-z_\\-]*",
cb_sp_test_task_detail, NULL);

mk_vhost_handler(ctx, vid, "/api/v1/stream_processor/task",
cb_sp_test_task_main, NULL);

Expand Down
85 changes: 83 additions & 2 deletions lib/monkey/include/monkey/mk_http_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@
#define MK_HTTP_PARSER_UPGRADE_H2 1
#define MK_HTTP_PARSER_UPGRADE_H2C 2

/* Transfer encoding */
#define MK_HTTP_PARSER_TRANSFER_ENCODING_NONE (0)
#define MK_HTTP_PARSER_TRANSFER_ENCODING_CHUNKED (1 << 0)
#define MK_HTTP_PARSER_TRANSFER_ENCODING_GZIP (1 << 1)

/* Transfer encoding (almost not used) */
#define MK_HTTP_PARSER_TRANSFER_ENCODING_COMPRESS (1 << 2)
#define MK_HTTP_PARSER_TRANSFER_ENCODING_DEFLATE (1 << 3)
#define MK_HTTP_PARSER_TRANSFER_ENCODING_IDENTITY (1 << 4)

#define MK_HEADER_EXTRA_SIZE 50

/* Request levels
Expand Down Expand Up @@ -118,6 +128,7 @@ enum mk_request_headers {
MK_HEADER_LAST_MODIFIED_SINCE ,
MK_HEADER_RANGE ,
MK_HEADER_REFERER ,
MK_HEADER_TRANSFER_ENCODING ,
MK_HEADER_UPGRADE ,
MK_HEADER_USER_AGENT ,
MK_HEADER_SIZEOF ,
Expand Down Expand Up @@ -193,6 +204,21 @@ struct mk_http_parser {
*/
int header_upgrade;


/*
* Transfer-Encoding
* ------------------
* we support the following values (bitwise):
*
* - MK_HTTP_PARSER_TRANSFER_ENCODING_NONE
* - MK_HTTP_PARSER_TRANSFER_ENCODING_CHUNKED
* - MK_HTTP_PARSER_TRANSFER_ENCODING_GZIP
* - MK_HTTP_PARSER_TRANSFER_ENCODING_COMPRESS
* - MK_HTTP_PARSER_TRANSFER_ENCODING_DEFLATE
* - MK_HTTP_PARSER_TRANSFER_ENCODING_IDENTITY
*/
int header_transfer_encoding;

/* probable current header, fly parsing */
int header_key;
int header_sep;
Expand All @@ -210,6 +236,20 @@ struct mk_http_parser {

/* Extra headers */
struct mk_http_header headers_extra[MK_HEADER_EXTRA_SIZE];


/*
* total size of bytes received as chunked data; this don't count the
* hex strings
*/
size_t chunk_total_size_received;

/* Transfer chunked encoding: state for active chunk being processed */
char *chunk_expected_start; /* pointer to the expected very first chunk in the payload */

size_t chunk_expected_size; /* expected size of a chunk being read */
char *chunk_processed_start; /* beginning of a chunk being read */
char *chunk_processed_end; /* last position of a chunk that is complete */
};


Expand Down Expand Up @@ -333,6 +373,20 @@ static inline void mk_http_parser_init(struct mk_http_parser *p)
mk_list_init(&p->header_list);
}

int mk_http_parser(struct mk_http_request *req, struct mk_http_parser *p,
char *buffer, int buf_len, struct mk_server *server);

size_t mk_http_parser_content_length(struct mk_http_parser *p);
int mk_http_parser_is_content_chunked(struct mk_http_parser *p);

int mk_http_parser_chunked_decode(struct mk_http_parser *p,
char *buf_request, size_t buf_request_len,
char **out_buf, size_t *out_buf_size);

int mk_http_parser_chunked_decode_buf(struct mk_http_parser *p,
char *buf_request, size_t buf_request_len,
char *out_buf, size_t out_buf_size, size_t *out_buf_len);

static inline int mk_http_parser_more(struct mk_http_parser *p, int len)
{
if (abs(len - p->i) - 1 > 0) {
Expand All @@ -342,7 +396,34 @@ static inline int mk_http_parser_more(struct mk_http_parser *p, int len)
return MK_FALSE;
}

int mk_http_parser(struct mk_http_request *req, struct mk_http_parser *p,
char *buffer, int buf_len, struct mk_server *server);
/* Returns the full size of the HTTP request in bytes "If" mk_http_parser() has returned MK_HTTP_PARSER_OK */
static inline size_t mk_http_parser_request_size(struct mk_http_parser *p, char *buf_request, size_t buf_request_len)
{
size_t bytes;

/*
* if the request is chunked encoded, p->i points to the beginning of the last chunk
* found, so we need to check if the last chunk is complete, if so we can return the
* size of the request
*/
if (mk_http_parser_is_content_chunked(p)) {
if (p->chunk_processed_start < buf_request) {
return -1;
}

/* Look at the last chunk processed (0\r\n\r\n) */
bytes = p->chunk_processed_start - buf_request + 5;
if (bytes > buf_request_len) {
return -1;
}
return bytes;
}
else if (p->header_content_length > 0) {
/* p->i points to the last byte after the content body */
return p->i;
}

return -1;
}

#endif /* MK_HTTP_H */
4 changes: 2 additions & 2 deletions lib/monkey/mk_core/mk_event_select.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,15 +367,15 @@ static inline int _mk_event_inject(struct mk_event_loop *loop,

if (prevent_duplication) {
for (index = 0 ; index < loop->n_events ; index++) {
if (ctx->fired[index]->fd == event->fd) {
if (ctx->fired[index].data == event) {
return 0;
}
}
}

event->mask = mask;

ctx->fired[loop->n_events] = event;
ctx->fired[loop->n_events].data = event;

loop->n_events++;

Expand Down
3 changes: 3 additions & 0 deletions lib/monkey/mk_server/mk_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,7 @@ int mk_http_request_end(struct mk_http_session *cs, struct mk_server *server)
mk_http_parser_init(&cs->parser);
status = mk_http_parser(sr, &cs->parser, cs->body, cs->body_length,
server);

if (status == MK_HTTP_PARSER_OK) {
ret = mk_http_request_prepare(cs, sr, server);
if (ret == MK_EXIT_ABORT) {
Expand Down Expand Up @@ -1564,8 +1565,10 @@ int mk_http_sched_read(struct mk_sched_conn *conn,
else {
sr = mk_list_entry_first(&cs->request_list, struct mk_http_request, _head);
}

status = mk_http_parser(sr, &cs->parser, cs->body,
cs->body_length, server);

if (status == MK_HTTP_PARSER_OK) {
MK_TRACE("[FD %i] HTTP_PARSER_OK", socket);
if (mk_http_status_completed(cs, conn) == -1) {
Expand Down
Loading
Loading