Merge pull request #358 from gwsystems/fix-http-session-state-machine

fix: correct HTTP session state machine
master
Sean McBride 3 years ago committed by GitHub
commit 2d35778c9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -35,9 +35,10 @@ enum http_session_state
HTTP_SESSION_EXECUTION_COMPLETE, HTTP_SESSION_EXECUTION_COMPLETE,
HTTP_SESSION_SENDING_RESPONSE_HEADER, HTTP_SESSION_SENDING_RESPONSE_HEADER,
HTTP_SESSION_SEND_RESPONSE_HEADER_BLOCKED, HTTP_SESSION_SEND_RESPONSE_HEADER_BLOCKED,
HTTP_SESSION_SENDING_RESPONSE, HTTP_SESSION_SENT_RESPONSE_HEADER,
HTTP_SESSION_SEND_RESPONSE_BLOCKED, HTTP_SESSION_SENDING_RESPONSE_BODY,
HTTP_SESSION_SENT_RESPONSE HTTP_SESSION_SEND_RESPONSE_BODY_BLOCKED,
HTTP_SESSION_SENT_RESPONSE_BODY
}; };
struct http_session { struct http_session {
@ -209,6 +210,9 @@ static inline int
http_session_send_response_header(struct http_session *session, void_star_cb on_eagain) http_session_send_response_header(struct http_session *session, void_star_cb on_eagain)
{ {
assert(session != NULL); 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) { while (session->response_header_length > session->response_header_written) {
ssize_t sent = 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; 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 != 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) { while (session->response_buffer_written < session->response_buffer.length) {
ssize_t sent = ssize_t sent =
tcp_session_send(session->socket, 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; return 0;
} }
@ -458,6 +469,8 @@ DONE:
static inline void static inline void
http_session_send_response(struct http_session *session, void_star_cb on_eagain) 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); int rc = http_session_send_response_header(session, on_eagain);
/* session blocked and registered to epoll so continue to next handle */ /* session blocked and registered to epoll so continue to next handle */
if (unlikely(rc == -EAGAIN)) { if (unlikely(rc == -EAGAIN)) {
@ -466,6 +479,8 @@ http_session_send_response(struct http_session *session, void_star_cb on_eagain)
goto CLOSE; goto CLOSE;
} }
assert(session->state == HTTP_SESSION_SENT_RESPONSE_HEADER);
rc = http_session_send_response_body(session, on_eagain); rc = http_session_send_response_body(session, on_eagain);
/* session blocked and registered to epoll so continue to next handle */ /* session blocked and registered to epoll so continue to next handle */
if (unlikely(rc == -EAGAIN)) { if (unlikely(rc == -EAGAIN)) {
@ -474,6 +489,8 @@ http_session_send_response(struct http_session *session, void_star_cb on_eagain)
goto CLOSE; goto CLOSE;
} }
assert(session->state == HTTP_SESSION_SENT_RESPONSE_BODY);
/* Terminal State Logging for Http Session */ /* Terminal State Logging for Http Session */
session->response_sent_timestamp = __getcycles(); session->response_sent_timestamp = __getcycles();
http_session_perf_log_print_entry(session); http_session_perf_log_print_entry(session);

@ -83,9 +83,9 @@ listener_thread_register_http_session(struct http_session *http)
accept_evt.events = EPOLLOUT; accept_evt.events = EPOLLOUT;
http->state = HTTP_SESSION_SEND_RESPONSE_HEADER_BLOCKED; http->state = HTTP_SESSION_SEND_RESPONSE_HEADER_BLOCKED;
break; break;
case HTTP_SESSION_SENDING_RESPONSE: case HTTP_SESSION_SENDING_RESPONSE_BODY:
accept_evt.events = EPOLLOUT; accept_evt.events = EPOLLOUT;
http->state = HTTP_SESSION_SEND_RESPONSE_BLOCKED; http->state = HTTP_SESSION_SEND_RESPONSE_BODY_BLOCKED;
break; break;
default: default:
panic("Invalid HTTP Session State: %d\n", http->state); panic("Invalid HTTP Session State: %d\n", http->state);
@ -251,9 +251,6 @@ on_client_request_received(struct http_session *session)
static void static void
on_client_response_header_sending(struct http_session *session) on_client_response_header_sending(struct http_session *session)
{ {
assert(session->state = HTTP_SESSION_EXECUTION_COMPLETE);
session->state = HTTP_SESSION_SENDING_RESPONSE_HEADER;
int rc = http_session_send_response_header(session, (void_star_cb)listener_thread_register_http_session); int rc = http_session_send_response_header(session, (void_star_cb)listener_thread_register_http_session);
if (likely(rc == 0)) { if (likely(rc == 0)) {
on_client_response_body_sending(session); on_client_response_body_sending(session);
@ -289,6 +286,8 @@ on_client_response_body_sending(struct http_session *session)
static void static void
on_client_response_sent(struct http_session *session) on_client_response_sent(struct http_session *session)
{ {
assert(session->state = HTTP_SESSION_SENT_RESPONSE_BODY);
/* Terminal State Logging for Http Session */ /* Terminal State Logging for Http Session */
session->response_sent_timestamp = __getcycles(); session->response_sent_timestamp = __getcycles();
http_session_perf_log_print_entry(session); http_session_perf_log_print_entry(session);
@ -343,7 +342,7 @@ on_client_socket_epoll_event(struct epoll_event *evt)
assert((evt->events & EPOLLOUT) == EPOLLOUT); assert((evt->events & EPOLLOUT) == EPOLLOUT);
on_client_response_header_sending(session); on_client_response_header_sending(session);
break; break;
case HTTP_SESSION_SEND_RESPONSE_BLOCKED: case HTTP_SESSION_SEND_RESPONSE_BODY_BLOCKED:
assert((evt->events & EPOLLOUT) == EPOLLOUT); assert((evt->events & EPOLLOUT) == EPOLLOUT);
on_client_response_body_sending(session); on_client_response_body_sending(session);
break; break;

Loading…
Cancel
Save