refactor: make code a bit cleaner n stuff
							parent
							
								
									2ff70c02c6
								
							
						
					
					
						commit
						6d45ec59dc
					
				|  | @ -14,47 +14,46 @@ | |||
| 
 | ||||
| #include "event_loop_internal.h" | ||||
| 
 | ||||
| const char http_200_ok[] = "HTTP/1.1 200 OK\nContent-Length: 5\n\nhello"; | ||||
| void event_loop_conn_io_res(event_loop_conn *conn) { | ||||
|   while (1) { | ||||
|     ssize_t res = 0; | ||||
|     size_t remain = conn->wbuf_size - conn->wbuf_sent; | ||||
| 
 | ||||
| bool event_loop_conn_io_res(event_loop_conn *conn) { | ||||
|   ssize_t res = 0; | ||||
|   size_t remain = conn->wbuf_size - conn->wbuf_sent; | ||||
|     do { | ||||
|       res = write(conn->fd, &conn->wbuf[conn->wbuf_sent], remain); | ||||
|     } while (res < 0 && errno == EINTR); | ||||
| 
 | ||||
|   do { | ||||
|     res = write(conn->fd, &conn->wbuf[conn->wbuf_sent], remain); | ||||
|   } while (res < 0 && errno == EINTR); | ||||
|     // EAGAIN doesn't mean there was an error, but rather that there's no more
 | ||||
|     // data right now, but there might be more later, aka "try again later"
 | ||||
|     if (res < 0 && errno == EAGAIN) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   // EAGAIN doesn't mean there was an error, but rather that there's no more
 | ||||
|   // data right now, but there might be more later, aka "try again later"
 | ||||
|   if (res < 0 && errno == EAGAIN) { | ||||
|     return false; | ||||
|     // If it's not EGAIN, there was an error writing so we simply end the
 | ||||
|     // request
 | ||||
|     if (res < 0) { | ||||
|       conn->state = event_loop_conn_state_end; | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     conn->wbuf_sent += (size_t)res; | ||||
| 
 | ||||
|     // After writing a response, we switch back to request mode to process a
 | ||||
|     // next request
 | ||||
|     if (conn->wbuf_sent == conn->wbuf_size) { | ||||
|       conn->state = conn->close_after_write ? event_loop_conn_state_end | ||||
|                                             : event_loop_conn_state_req; | ||||
|       /* c->wbuf_sent = 0; */ | ||||
|       /* c->wbuf_size = 0; */ | ||||
| 
 | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // If it's not EGAIN, there was an error writing so we simply end the request
 | ||||
|   if (res < 0) { | ||||
|     conn->state = event_loop_conn_state_end; | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   conn->wbuf_sent += (size_t)res; | ||||
| 
 | ||||
|   // After writing a response, we switch back to request mode to process a next
 | ||||
|   // request
 | ||||
|   if (conn->wbuf_sent == conn->wbuf_size) { | ||||
|     conn->state = conn->close_after_write ? event_loop_conn_state_end | ||||
|                                           : event_loop_conn_state_req; | ||||
|     /* c->wbuf_sent = 0; */ | ||||
|     /* c->wbuf_size = 0; */ | ||||
| 
 | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   // still got some data in wbuf, could try to write again
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool try_one_request(event_loop_conn *conn) { | ||||
|   // We definitely can't do anything with zero bytes.
 | ||||
| bool event_loop_handle_request(event_loop_conn *conn) { | ||||
|   // Prevents the request handler function from looping indefinitely without
 | ||||
|   // ever consuming new data
 | ||||
|   if (conn->rbuf_size == 0) { | ||||
|     return false; | ||||
|   } | ||||
|  | @ -117,76 +116,68 @@ bool try_one_request(event_loop_conn *conn) { | |||
|  * | ||||
|  * Returns whether the function should be retried immediately or not. | ||||
|  */ | ||||
| bool event_loop_conn_io_req(event_loop_conn *conn) { | ||||
|   ssize_t res; | ||||
|   size_t cap = EVENT_LOOP_BUFFER_SIZE - conn->rbuf_size; | ||||
| void event_loop_conn_io_req(event_loop_conn *conn) { | ||||
|   while (1) { | ||||
|     ssize_t res; | ||||
|     size_t cap = EVENT_LOOP_BUFFER_SIZE - conn->rbuf_size; | ||||
| 
 | ||||
|   // Try to read at most cap bytes from the file descriptor
 | ||||
|   do { | ||||
|     res = read(conn->fd, &conn->rbuf[conn->rbuf_size], cap); | ||||
|   } while (res < 0 && errno == EINTR); | ||||
|     // Try to read at most cap bytes from the file descriptor
 | ||||
|     do { | ||||
|       res = read(conn->fd, &conn->rbuf[conn->rbuf_size], cap); | ||||
|     } while (res < 0 && errno == EINTR); | ||||
| 
 | ||||
|   // EGAIN means we try again later
 | ||||
|   if (res < 0 && errno == EAGAIN) { | ||||
|     return false; | ||||
|   } | ||||
|     // EGAIN means we try again later
 | ||||
|     if (res < 0 && errno == EAGAIN) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   // Any other negative error message means the read errored out
 | ||||
|   if (res < 0) { | ||||
|     conn->state = event_loop_conn_state_end; | ||||
|     // Any other negative error message means the read errored out
 | ||||
|     if (res < 0) { | ||||
|       conn->state = event_loop_conn_state_end; | ||||
| 
 | ||||
|     return false; | ||||
|   } | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   // Output of 0 and no error means we've reached the end of the input. We run
 | ||||
|   // try_one_request one more time and close the connection if this doesn't
 | ||||
|   // change the result.
 | ||||
|   if (res == 0) { | ||||
|     conn->state = event_loop_conn_state_end; | ||||
|     // Output of 0 and no error means we've reached the end of the input. We run
 | ||||
|     // try_one_request one more time and close the connection if this doesn't
 | ||||
|     // change the result.
 | ||||
|     if (res == 0) { | ||||
|       conn->state = event_loop_conn_state_end; | ||||
| 
 | ||||
|     return false; | ||||
|   } | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   // We switch to processing mode if we've reached the end of the data stream,
 | ||||
|   // or if the read buffer is filled
 | ||||
|   /* if (res == 0 || c->rbuf_size == MAX_MSG_SIZE) { */ | ||||
|   /*     c->state = STATE_PROCESS; */ | ||||
|   /*     return false; */ | ||||
|   /* } */ | ||||
|     // We switch to processing mode if we've reached the end of the data stream,
 | ||||
|     // or if the read buffer is filled
 | ||||
|     /* if (res == 0 || c->rbuf_size == MAX_MSG_SIZE) { */ | ||||
|     /*     c->state = STATE_PROCESS; */ | ||||
|     /*     return false; */ | ||||
|     /* } */ | ||||
| 
 | ||||
|   conn->rbuf_size += (size_t)res; | ||||
|     conn->rbuf_size += (size_t)res; | ||||
| 
 | ||||
|   /* assert(conn->rbuf_size <= sizeof(conn->rbuf)); */ | ||||
|     /* assert(conn->rbuf_size <= sizeof(conn->rbuf)); */ | ||||
| 
 | ||||
|   // Try to process requests one by one.
 | ||||
|   // Try to process requests one by one.
 | ||||
|   // Why is there a loop? Please read the explanation of "pipelining".
 | ||||
|   while (try_one_request(conn)) { | ||||
|   }; | ||||
|     // Try to process requests one by one.
 | ||||
|     // Try to process requests one by one.
 | ||||
|     // Why is there a loop? Please read the explanation of "pipelining".
 | ||||
|     while (event_loop_handle_request(conn)) { | ||||
|     }; | ||||
| 
 | ||||
|   // We can keep reading as long as we're in request mode
 | ||||
|   return conn->state == event_loop_conn_state_req; | ||||
|   /* while (try_one_request(conn)) {} */ | ||||
|   /* return (conn->state == STATE_REQ); */ | ||||
| } | ||||
| 
 | ||||
| void conn_state_res(event_loop_conn *conn) { | ||||
|   while (event_loop_conn_io_res(conn)) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void conn_state_req(event_loop_conn *conn) { | ||||
|   while (event_loop_conn_io_req(conn)) { | ||||
|     // We can keep reading as long as we're in request mode
 | ||||
|     if (conn->state != event_loop_conn_state_req) { | ||||
|       return; | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void event_loop_conn_io(event_loop_conn *conn) { | ||||
|   switch (conn->state) { | ||||
|   case event_loop_conn_state_req: | ||||
|     conn_state_req(conn); | ||||
|     event_loop_conn_io_req(conn); | ||||
|     break; | ||||
|   case event_loop_conn_state_res: | ||||
|     conn_state_res(conn); | ||||
|     event_loop_conn_io_res(conn); | ||||
|     break; | ||||
|   case event_loop_conn_state_end: | ||||
|     printf("we shouldn't be here\n"); | ||||
|  |  | |||
|  | @ -0,0 +1,11 @@ | |||
| #include <stdlib.h> | ||||
| 
 | ||||
| const char http_404[] = "HTTP/1.1 404 Not Found\n" | ||||
|                         "Connection: close\n" | ||||
|                         "Content-Length: 0\n\n"; | ||||
| const size_t http_404_len = sizeof(http_404) - 1; | ||||
| 
 | ||||
| const char http_500[] = "HTTP/1.1 500 Internal Server Error\n" | ||||
|                         "Connection: close\n" | ||||
|                         "Content-Length: 0\n\n"; | ||||
| const size_t http_500_len = sizeof(http_500) - 1; | ||||
|  | @ -53,4 +53,9 @@ int event_loop_accept(event_loop *loop, int fd); | |||
| 
 | ||||
| void event_loop_conn_io(event_loop_conn *conn); | ||||
| 
 | ||||
| extern const char http_404[]; | ||||
| extern const size_t http_404_len; | ||||
| extern const char http_500[]; | ||||
| extern const size_t http_500_len; | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue