refactor: make code a bit cleaner n stuff

c-web-server
Jef Roosens 2023-05-25 09:26:53 +02:00
parent 2ff70c02c6
commit 6d45ec59dc
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
3 changed files with 93 additions and 86 deletions

View File

@ -14,47 +14,46 @@
#include "event_loop_internal.h" #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) { do {
ssize_t res = 0; res = write(conn->fd, &conn->wbuf[conn->wbuf_sent], remain);
size_t remain = conn->wbuf_size - conn->wbuf_sent; } while (res < 0 && errno == EINTR);
do { // EAGAIN doesn't mean there was an error, but rather that there's no more
res = write(conn->fd, &conn->wbuf[conn->wbuf_sent], remain); // data right now, but there might be more later, aka "try again later"
} while (res < 0 && errno == EINTR); if (res < 0 && errno == EAGAIN) {
return;
}
// EAGAIN doesn't mean there was an error, but rather that there's no more // If it's not EGAIN, there was an error writing so we simply end the
// data right now, but there might be more later, aka "try again later" // request
if (res < 0 && errno == EAGAIN) { if (res < 0) {
return false; 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) { bool event_loop_handle_request(event_loop_conn *conn) {
// We definitely can't do anything with zero bytes. // Prevents the request handler function from looping indefinitely without
// ever consuming new data
if (conn->rbuf_size == 0) { if (conn->rbuf_size == 0) {
return false; return false;
} }
@ -117,76 +116,68 @@ bool try_one_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.
*/ */
bool event_loop_conn_io_req(event_loop_conn *conn) { void event_loop_conn_io_req(event_loop_conn *conn) {
ssize_t res; while (1) {
size_t cap = EVENT_LOOP_BUFFER_SIZE - conn->rbuf_size; ssize_t res;
size_t cap = EVENT_LOOP_BUFFER_SIZE - conn->rbuf_size;
// Try to read at most cap bytes from the file descriptor // Try to read at most cap bytes from the file descriptor
do { do {
res = read(conn->fd, &conn->rbuf[conn->rbuf_size], cap); res = read(conn->fd, &conn->rbuf[conn->rbuf_size], cap);
} while (res < 0 && errno == EINTR); } while (res < 0 && errno == EINTR);
// EGAIN means we try again later // EGAIN means we try again later
if (res < 0 && errno == EAGAIN) { if (res < 0 && errno == EAGAIN) {
return false; return;
} }
// Any other negative error message means the read errored out // Any other negative error message means the read errored out
if (res < 0) { if (res < 0) {
conn->state = event_loop_conn_state_end; 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 // 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 // try_one_request one more time and close the connection if this doesn't
// change the result. // change the result.
if (res == 0) { if (res == 0) {
conn->state = event_loop_conn_state_end; 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, // We switch to processing mode if we've reached the end of the data stream,
// or if the read buffer is filled // or if the read buffer is filled
/* if (res == 0 || c->rbuf_size == MAX_MSG_SIZE) { */ /* if (res == 0 || c->rbuf_size == MAX_MSG_SIZE) { */
/* c->state = STATE_PROCESS; */ /* c->state = STATE_PROCESS; */
/* return false; */ /* 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.
// 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". // Why is there a loop? Please read the explanation of "pipelining".
while (try_one_request(conn)) { while (event_loop_handle_request(conn)) {
}; };
// We can keep reading as long as we're in request mode // We can keep reading as long as we're in request mode
return conn->state == event_loop_conn_state_req; if (conn->state != event_loop_conn_state_req) {
/* while (try_one_request(conn)) {} */ return;
/* 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)) {
} }
} }
void event_loop_conn_io(event_loop_conn *conn) { void event_loop_conn_io(event_loop_conn *conn) {
switch (conn->state) { switch (conn->state) {
case event_loop_conn_state_req: case event_loop_conn_state_req:
conn_state_req(conn); event_loop_conn_io_req(conn);
break; break;
case event_loop_conn_state_res: case event_loop_conn_state_res:
conn_state_res(conn); event_loop_conn_io_res(conn);
break; break;
case event_loop_conn_state_end: case event_loop_conn_state_end:
printf("we shouldn't be here\n"); printf("we shouldn't be here\n");

View File

@ -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;

View File

@ -53,4 +53,9 @@ int event_loop_accept(event_loop *loop, int fd);
void event_loop_conn_io(event_loop_conn *conn); 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 #endif