From 066876d4910b73362dea74f8760df390f0b3c83a Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 18 Aug 2022 13:36:54 -0400 Subject: [PATCH] fix: HTTP session state machine --- runtime/include/http_session.h | 23 ++++++++++++++++++++--- runtime/src/listener_thread.c | 13 ++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/runtime/include/http_session.h b/runtime/include/http_session.h index 2252f64..8ef7f69 100644 --- a/runtime/include/http_session.h +++ b/runtime/include/http_session.h @@ -35,9 +35,10 @@ enum http_session_state HTTP_SESSION_EXECUTION_COMPLETE, HTTP_SESSION_SENDING_RESPONSE_HEADER, HTTP_SESSION_SEND_RESPONSE_HEADER_BLOCKED, - HTTP_SESSION_SENDING_RESPONSE, - HTTP_SESSION_SEND_RESPONSE_BLOCKED, - HTTP_SESSION_SENT_RESPONSE + HTTP_SESSION_SENT_RESPONSE_HEADER, + HTTP_SESSION_SENDING_RESPONSE_BODY, + HTTP_SESSION_SEND_RESPONSE_BODY_BLOCKED, + HTTP_SESSION_SENT_RESPONSE_BODY }; struct http_session { @@ -209,6 +210,9 @@ static inline int http_session_send_response_header(struct http_session *session, void_star_cb on_eagain) { assert(session != NULL); + assert(session->state == HTTP_SESSION_EXECUTION_COMPLETE + || session->state == HTTP_SESSION_SEND_RESPONSE_HEADER_BLOCKED); + session->state = HTTP_SESSION_SENDING_RESPONSE_HEADER; while (session->response_header_length > session->response_header_written) { ssize_t sent = @@ -223,6 +227,8 @@ http_session_send_response_header(struct http_session *session, void_star_cb on_ } } + session->state = HTTP_SESSION_SENT_RESPONSE_HEADER; + return 0; } @@ -237,6 +243,10 @@ http_session_send_response_body(struct http_session *session, void_star_cb on_ea { assert(session != NULL); + assert(session->state == HTTP_SESSION_SENT_RESPONSE_HEADER + || session->state == HTTP_SESSION_SEND_RESPONSE_BODY_BLOCKED); + session->state = HTTP_SESSION_SENDING_RESPONSE_BODY; + while (session->response_buffer_written < session->response_buffer.length) { ssize_t sent = tcp_session_send(session->socket, @@ -250,6 +260,7 @@ http_session_send_response_body(struct http_session *session, void_star_cb on_ea } } + session->state = HTTP_SESSION_SENT_RESPONSE_BODY; return 0; } @@ -458,6 +469,8 @@ DONE: static inline void http_session_send_response(struct http_session *session, void_star_cb on_eagain) { + assert(session->state == HTTP_SESSION_EXECUTION_COMPLETE); + int rc = http_session_send_response_header(session, on_eagain); /* session blocked and registered to epoll so continue to next handle */ if (unlikely(rc == -EAGAIN)) { @@ -466,6 +479,8 @@ http_session_send_response(struct http_session *session, void_star_cb on_eagain) goto CLOSE; } + assert(session->state == HTTP_SESSION_SENT_RESPONSE_HEADER); + rc = http_session_send_response_body(session, on_eagain); /* session blocked and registered to epoll so continue to next handle */ if (unlikely(rc == -EAGAIN)) { @@ -474,6 +489,8 @@ http_session_send_response(struct http_session *session, void_star_cb on_eagain) goto CLOSE; } + assert(session->state == HTTP_SESSION_SENT_RESPONSE_BODY); + /* Terminal State Logging for Http Session */ session->response_sent_timestamp = __getcycles(); http_session_perf_log_print_entry(session); diff --git a/runtime/src/listener_thread.c b/runtime/src/listener_thread.c index f615db8..221814e 100644 --- a/runtime/src/listener_thread.c +++ b/runtime/src/listener_thread.c @@ -84,9 +84,9 @@ listener_thread_register_http_session(struct http_session *http) accept_evt.events = EPOLLOUT; http->state = HTTP_SESSION_SEND_RESPONSE_HEADER_BLOCKED; break; - case HTTP_SESSION_SENDING_RESPONSE: + case HTTP_SESSION_SENDING_RESPONSE_BODY: accept_evt.events = EPOLLOUT; - http->state = HTTP_SESSION_SEND_RESPONSE_BLOCKED; + http->state = HTTP_SESSION_SEND_RESPONSE_BODY_BLOCKED; break; default: panic("Invalid HTTP Session State: %d\n", http->state); @@ -252,8 +252,7 @@ on_client_request_received(struct http_session *session) static void on_client_response_header_sending(struct http_session *session) { - assert(session->state = HTTP_SESSION_EXECUTION_COMPLETE); - session->state = HTTP_SESSION_SENDING_RESPONSE_HEADER; + assert(session->state = HTTP_SESSION_SEND_RESPONSE_HEADER_BLOCKED); int rc = http_session_send_response_header(session, (void_star_cb)listener_thread_register_http_session); if (likely(rc == 0)) { @@ -272,6 +271,8 @@ on_client_response_header_sending(struct http_session *session) static void on_client_response_body_sending(struct http_session *session) { + assert(session->state = HTTP_SESSION_SEND_RESPONSE_BODY_BLOCKED); + /* Read HTTP request */ int rc = http_session_send_response_body(session, (void_star_cb)listener_thread_register_http_session); if (likely(rc == 0)) { @@ -290,6 +291,8 @@ on_client_response_body_sending(struct http_session *session) static void on_client_response_sent(struct http_session *session) { + assert(session->state = HTTP_SESSION_SENT_RESPONSE_BODY); + /* Terminal State Logging for Http Session */ session->response_sent_timestamp = __getcycles(); http_session_perf_log_print_entry(session); @@ -344,7 +347,7 @@ on_client_socket_epoll_event(struct epoll_event *evt) assert((evt->events & EPOLLOUT) == EPOLLOUT); on_client_response_header_sending(session); break; - case HTTP_SESSION_SEND_RESPONSE_BLOCKED: + case HTTP_SESSION_SEND_RESPONSE_BODY_BLOCKED: assert((evt->events & EPOLLOUT) == EPOLLOUT); on_client_response_body_sending(session); break;