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_invalid = 2,
|
||||||
} http_parse_error;
|
} 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
|
#endif
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "picohttpparser.h"
|
#include "picohttpparser.h"
|
||||||
|
#include "http.h"
|
||||||
|
|
||||||
#include "event_loop_internal.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) {
|
bool event_loop_handle_request(event_loop_conn *conn) {
|
||||||
// Prevents the request handler function from looping indefinitely without
|
// Prevents the request handler function from looping indefinitely without
|
||||||
// ever consuming new data
|
// ever consuming new data
|
||||||
if (conn->rbuf_size == 0) {
|
if (conn->rbuf_size - conn->rbuf_read == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ bool event_loop_handle_request(event_loop_conn *conn) {
|
||||||
|
|
||||||
num_headers = sizeof(headers) / sizeof(headers[0]);
|
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,
|
&method, &method_len, &path, &path_len,
|
||||||
&minor_version, headers, &num_headers, 0);
|
&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++) { */
|
/* for (size_t i = 0; i < num_headers; i++) { */
|
||||||
/* /1* printf("%.*s: ", headers[i].name_len, headers[i].name); *1/ */
|
/* /1* printf("%.*s: ", headers[i].name_len, headers[i].name); *1/ */
|
||||||
/* /1* printf("%.*s\n", headers[i].value_len, headers[i].value); *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("Connection", headers[i].name, headers[i].name_len) == 0) {
|
||||||
/* if (strncmp("close", headers[i].value, headers[i].value_len) == 0) { */
|
*/
|
||||||
|
/* if (strncmp("close", headers[i].value, headers[i].value_len) == 0) {
|
||||||
|
*/
|
||||||
/* conn->close_after_write = true; */
|
/* conn->close_after_write = true; */
|
||||||
/* break; */
|
/* 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); */
|
/* memmove(conn->rbuf, &conn->rbuf[res], conn->rbuf_size - res); */
|
||||||
/* conn->rbuf_size -= res; */
|
/* conn->rbuf_size -= res; */
|
||||||
|
|
||||||
/* conn->state = event_loop_conn_state_res; */
|
conn->state = event_loop_conn_state_res;
|
||||||
/* conn->wbuf_size = http_500_len; */
|
conn->wbuf_size = http_404_len;
|
||||||
/* conn->wbuf_sent = 0; */
|
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 */
|
/* // is too large to fit into a single read buffer */
|
||||||
} else if (res == -1 ||
|
} else if (res == -1 ||
|
||||||
(res == -2 && conn->rbuf_size == EVENT_LOOP_BUFFER_SIZE)) {
|
(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.
|
* Returns whether the function should be retried immediately or not.
|
||||||
*/
|
*/
|
||||||
void event_loop_conn_io_req(event_loop_conn *conn) {
|
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;
|
ssize_t res;
|
||||||
size_t cap = EVENT_LOOP_BUFFER_SIZE - conn->rbuf_size;
|
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;
|
conn->rbuf_size += (size_t)res;
|
||||||
|
|
||||||
/* assert(conn->rbuf_size <= sizeof(conn->rbuf)); */
|
// This loop allows processing multiple requests from a single read buffer
|
||||||
|
while (event_loop_handle_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
|
|
||||||
if (conn->state != event_loop_conn_state_req) {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
// 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) {
|
void event_loop_conn_io(event_loop_conn *conn) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ typedef struct event_loop_conn {
|
||||||
event_loop_conn_state state;
|
event_loop_conn_state state;
|
||||||
// buffer for reading
|
// buffer for reading
|
||||||
size_t rbuf_size;
|
size_t rbuf_size;
|
||||||
|
size_t rbuf_read;
|
||||||
uint8_t rbuf[EVENT_LOOP_BUFFER_SIZE];
|
uint8_t rbuf[EVENT_LOOP_BUFFER_SIZE];
|
||||||
// buffer for writing
|
// buffer for writing
|
||||||
size_t wbuf_size;
|
size_t wbuf_size;
|
||||||
|
|
|
@ -4,16 +4,17 @@
|
||||||
/*
|
/*
|
||||||
* given the HTTP path, parse the request
|
* 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
|
// First we try to parse the incoming HTTP request
|
||||||
const char *method, *path;
|
const char *method, *path;
|
||||||
struct phr_header headers[16];
|
struct phr_header headers[16];
|
||||||
size_t method_len, path_len, num_headers;
|
size_t method_len, path_len, num_headers;
|
||||||
int minor_version;
|
int minor_version;
|
||||||
|
|
||||||
int res = phr_parse_request(buf, buf_size,
|
int res =
|
||||||
&method, &method_len, &path, &path_len,
|
phr_parse_request(buf, buf_size, &method, &method_len, &path, &path_len,
|
||||||
&minor_version, headers, &num_headers, 0);
|
&minor_version, headers, &num_headers, 0);
|
||||||
|
|
||||||
if (res == -2) {
|
if (res == -2) {
|
||||||
return http_parse_error_incomplete;
|
return http_parse_error_incomplete;
|
||||||
|
|
Loading…
Reference in New Issue