feat: only memmove read buffer on read
							parent
							
								
									c58e53eb2a
								
							
						
					
					
						commit
						32687e0b49
					
				|  | @ -34,6 +34,7 @@ typedef enum http_parse_error { | |||
|   http_parse_error_invalid = 2, | ||||
| } http_parse_error; | ||||
| 
 | ||||
| http_parse_error http_parse_request(http_request *req, const char *path, size_t path_len); | ||||
| http_parse_error http_parse_request(http_request *req, const char *path, | ||||
|                                     size_t path_len); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ | |||
| #include <unistd.h> | ||||
| 
 | ||||
| #include "picohttpparser.h" | ||||
| #include "http.h" | ||||
| 
 | ||||
| #include "event_loop_internal.h" | ||||
| 
 | ||||
|  | @ -54,7 +55,7 @@ void event_loop_conn_io_res(event_loop_conn *conn) { | |||
| 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) { | ||||
|   if (conn->rbuf_size - conn->rbuf_read == 0) { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|  | @ -69,7 +70,7 @@ bool event_loop_handle_request(event_loop_conn *conn) { | |||
| 
 | ||||
|   num_headers = sizeof(headers) / sizeof(headers[0]); | ||||
| 
 | ||||
|   int res = phr_parse_request((const char *)conn->rbuf, conn->rbuf_size, | ||||
|   int res = phr_parse_request((const char *)&conn->rbuf[conn->rbuf_read], conn->rbuf_size - conn->rbuf_read, | ||||
|                               &method, &method_len, &path, &path_len, | ||||
|                               &minor_version, headers, &num_headers, 0); | ||||
| 
 | ||||
|  | @ -77,27 +78,33 @@ bool event_loop_handle_request(event_loop_conn *conn) { | |||
|     /* for (size_t i = 0; i < num_headers; i++) { */ | ||||
|     /*   /1* printf("%.*s: ", headers[i].name_len, headers[i].name); *1/ */ | ||||
|     /*   /1* printf("%.*s\n", headers[i].value_len, headers[i].value); *1/ */ | ||||
|     /*   if (strncmp("Connection", headers[i].name, headers[i].name_len) == 0) { */ | ||||
|     /*     if (strncmp("close", headers[i].value, headers[i].value_len) == 0) { */ | ||||
|     /*   if (strncmp("Connection", headers[i].name, headers[i].name_len) == 0) {
 | ||||
|      */ | ||||
|     /*     if (strncmp("close", headers[i].value, headers[i].value_len) == 0) {
 | ||||
|      */ | ||||
|     /*       conn->close_after_write = true; */ | ||||
|     /*       break; */ | ||||
|     /*     } */ | ||||
|     /*   } */ | ||||
|     /* } */ | ||||
| 
 | ||||
|     /* memcpy(conn->wbuf, http_500, http_500_len); */ | ||||
|     // Advance the read buffer
 | ||||
|     conn->rbuf_read += res; | ||||
| 
 | ||||
|     /* // Move the new request up to the front of the read buffer */ | ||||
|     memcpy(conn->wbuf, http_404, http_404_len); | ||||
| 
 | ||||
|     // Move the new request up to the front of the read buffer
 | ||||
|     /* memmove(conn->rbuf, &conn->rbuf[res], conn->rbuf_size - res); */ | ||||
|     /* conn->rbuf_size -= res; */ | ||||
| 
 | ||||
|     /* conn->state = event_loop_conn_state_res; */ | ||||
|     /* conn->wbuf_size = http_500_len; */ | ||||
|     /* conn->wbuf_sent = 0; */ | ||||
|     conn->state = event_loop_conn_state_res; | ||||
|     conn->wbuf_size = http_404_len; | ||||
|     conn->wbuf_sent = 0; | ||||
| 
 | ||||
|     /* /1* event_loop_conn_io_res(conn); *1/ */ | ||||
|     event_loop_conn_io_res(conn); | ||||
| 
 | ||||
|     /* // End the connection if the http request is invalid, or when the response */ | ||||
|     /* // End the connection if the http request is invalid, or when the
 | ||||
|      * response */ | ||||
|     /* // is too large to fit into a single read buffer */ | ||||
|   } else if (res == -1 || | ||||
|              (res == -2 && conn->rbuf_size == EVENT_LOOP_BUFFER_SIZE)) { | ||||
|  | @ -114,7 +121,12 @@ bool event_loop_handle_request(event_loop_conn *conn) { | |||
|  * Returns whether the function should be retried immediately or not. | ||||
|  */ | ||||
| void event_loop_conn_io_req(event_loop_conn *conn) { | ||||
|   while (1) { | ||||
|   do { | ||||
|     // Move remaining data to start of buffer
 | ||||
|     memmove(conn->rbuf, &conn->rbuf[conn->rbuf_read], conn->rbuf_size - conn->rbuf_read); | ||||
|     conn->rbuf_size -= conn->rbuf_read; | ||||
|     conn->rbuf_read = 0; | ||||
| 
 | ||||
|     ssize_t res; | ||||
|     size_t cap = EVENT_LOOP_BUFFER_SIZE - conn->rbuf_size; | ||||
| 
 | ||||
|  | @ -153,19 +165,12 @@ void event_loop_conn_io_req(event_loop_conn *conn) { | |||
| 
 | ||||
|     conn->rbuf_size += (size_t)res; | ||||
| 
 | ||||
|     /* 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 (event_loop_handle_request(conn)) { | ||||
|     }; | ||||
| 
 | ||||
|     // We can keep reading as long as we're in request mode
 | ||||
|     if (conn->state != event_loop_conn_state_req) { | ||||
|       return; | ||||
|     }; | ||||
|     // This loop allows processing multiple requests from a single read buffer
 | ||||
|     while (event_loop_handle_request(conn)) | ||||
|       ; | ||||
|   } | ||||
|   // We can keep reading as long as we're in request mode
 | ||||
|   while (conn->state == event_loop_conn_state_req); | ||||
| } | ||||
| 
 | ||||
| void event_loop_conn_io(event_loop_conn *conn) { | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ typedef struct event_loop_conn { | |||
|   event_loop_conn_state state; | ||||
|   // buffer for reading
 | ||||
|   size_t rbuf_size; | ||||
|   size_t rbuf_read; | ||||
|   uint8_t rbuf[EVENT_LOOP_BUFFER_SIZE]; | ||||
|   // buffer for writing
 | ||||
|   size_t wbuf_size; | ||||
|  |  | |||
|  | @ -4,16 +4,17 @@ | |||
| /*
 | ||||
|  * given the HTTP path, parse the request | ||||
|  */ | ||||
| http_parse_error http_parse_request(http_request *req, const char *buf, size_t buf_size) { | ||||
| http_parse_error http_parse_request(http_request *req, const char *buf, | ||||
|                                     size_t buf_size) { | ||||
|   // First we try to parse the incoming HTTP request
 | ||||
|   const char *method, *path; | ||||
|   struct phr_header headers[16]; | ||||
|   size_t method_len, path_len, num_headers; | ||||
|   int minor_version; | ||||
| 
 | ||||
|   int res = phr_parse_request(buf, buf_size, | ||||
|                               &method, &method_len, &path, &path_len, | ||||
|                               &minor_version, headers, &num_headers, 0); | ||||
|   int res = | ||||
|       phr_parse_request(buf, buf_size, &method, &method_len, &path, &path_len, | ||||
|                         &minor_version, headers, &num_headers, 0); | ||||
| 
 | ||||
|   if (res == -2) { | ||||
|     return http_parse_error_incomplete; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue